天道不一定酬所有勤
但是,天道只酬勤

為什么Java要把字符串設計成不可變的

String是Java中一個不可變的類,所以他一旦被實例化就無法被修改。不可變類的實例一旦創建,其成員變量的值就不能被修改。不可變類有很多優勢。本文總結了為什么字符串被設計成不可變的。將涉及到內存、同步和數據結構相關的知識。

字符串池

字符串池是方法區中的一部分特殊存儲。當一個字符串被被創建的時候,首先會去這個字符串池中查找,如果找到,直接返回對該字符串的引用。

下面的代碼只會在堆中創建一個字符串

String string1 = "abcd";
String string2 = "abcd";

下面是圖示:

string

如果字符串可變的話,當兩個引用指向指向同一個字符串時,對其中一個做修改就會影響另外一個。(請記住該影響,有助于理解后面的內容)

緩存Hashcode

Java中經常會用到字符串的哈希碼(hashcode)。例如,在HashMap中,字符串的不可變能保證其hashcode永遠保持一致,這樣就可以避免一些不必要的麻煩。這也就意味著每次在使用一個字符串的hashcode的時候不用重新計算一次,這樣更加高效。

在String類中,有以下代碼:

private int hash;//this is used to cache hash code.

以上代碼中hash變量中就保存了一個String對象的hashcode,因為String類不可變,所以一旦對象被創建,該hash值也無法改變。所以,每次想要使用該對象的hashcode的時候,直接返回即可。

使其他類的使用更加便利

在介紹這個內容之前,先看以下代碼:

HashSet<String> set = new HashSet<String>();
set.add(new String("a"));
set.add(new String("b"));
set.add(new String("c"));

for(String a: set)
    a.value = "a";

在上面的例子中,如果字符串可以被改變,那么以上用法將有可能違反Set的設計原則,因為Set要求其中的元素不可以重復。上面的代碼只是為了簡單說明該問題,其實String類中并沒有value這個字段值。

安全性

String被廣泛的使用在其他Java類中充當參數。比如網絡連接、打開文件等操作。如果字符串可變,那么類似操作可能導致安全問題。因為某個方法在調用連接操作的時候,他認為會連接到某臺機器,但是實際上并沒有(其他引用同一String對象的值修改會導致該連接中的字符串內容被修改)??勺兊淖址部赡軐е路瓷涞陌踩珕栴},因為他的參數也是字符串。

代碼示例:

boolean connect(string s){
    if (!isSecure(s)) { 
throw new SecurityException(); 
}
    //如果s在該操作之前被其他的引用所改變,那么就可能導致問題。   
    causeProblem(s);
}

不可變對象天生就是線程安全的

因為不可變對象不能被改變,所以他們可以自由地在多個線程之間共享。不需要任何同步處理。

總之,String被設計成不可變的主要目的是為了安全和高效。所以,使String是一個不可變類是一個很好的設計。

(全文完) 歡迎關注『Java之道』微信公眾號
贊(7)
如未加特殊說明,此網站文章均為原創,轉載必須注明出處。HollisChuang's Blog » 為什么Java要把字符串設計成不可變的
分享到: 更多 (0)

評論 5

  • 昵稱 (必填)
  • 郵箱 (必填)
  • 網址
  1. #1

    本文就是胡說八道!
    既然不可變有這么多優勢,為啥不把其他類都弄成不可變的 ?

    天空4年前 (2016-03-03)回復
    • 你這直接給我問蒙了,,,不過我想大概是這樣,比如String a = abcd; a = defc; 這樣其實是在內存中又新開辟了空間給了defc,然后把a的引用指向defc;如果大家都是不可變類,那每次賦值豈不是要都新開辟空間,盡管jvm有gc,,估計它也忙不過來

      皇阿瑪2年前 (2018-03-29)回復
    • 杠精,工地搬磚需要你這種人才

      learnBug7個月前 (09-12)回復
  2. #2

    原文中:當兩個引用指向指向同一個字符串時,對其中一個做修改就會影響另外一個;;;
    如果修改其中一個,不應該是被修改的引用指向新字符串么,,,對原來的那個沒被修改的有啥影響啊

    皇阿瑪2年前 (2018-03-29)回復
    • 前面還有一句話:如果字符串可變的話

      若即若離2年前 (2018-04-30)回復

HollisChuang's Blog

聯系我關于我
大乐透复式返奖 排列三开奖官网 北京pk10注册 青海十一选五最新开奖历史 在上海有哪些配资公司 11选5玩法 吉林快三预测专家预测软件 炒股app 山东体彩快乐扑克开奖结果走势图 云南快乐十分开奖助手 重庆时彩时彩官网