原文地址:# Why String is immutable in Java?java
衆所周知,String類在Java中是不可變的。不可變類簡單地說是實例不可修改的類。對於一個實例建立後,其初始化的時候全部的信息都不能被修改。不可變類有不少的好處,本文簡述爲何String類要設計成不可變類。本文將從內存,同步性,數據結構的角度說明不變性的概念。緩存
###1.字符串常量池的須要 String常量池是方法區的一個特殊的儲存區。當新建一個字符串的時候,若是此字符串在常量池中早已存在,會返回一個已經存在字符串的引用,而不是新建一個對象。 如下代碼展現了只會在堆內存(String常量池就是位於堆內存中)中建立一個String對象。安全
String string1 = "abcd"; String string2 = "abcd";
來張圖生動地解釋下: 最後,設想一下,若是String可變,那麼用某個引用一旦改變了字符串的值將會致使其餘引用指向錯誤的值。 ###2.緩存 Hashcode 字符串的hashcode
在Java中頻繁地使用,好比在HashMap 或者 HashSet。hashcode
始終相同成爲了字符串不變的保證,因此能夠在操做的時候能夠沒必要擔憂改變。這也就意味着,不用每次使用的時候都要計算其hashcode
,這樣更高效。 在String類中,有以下代碼:網絡
private int hash;//this is used to cache hash code.
###3.使其餘對象使用更加方便 來具體地解釋下,看下方代碼:數據結構
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";
設想一下,若是String可變(也就是添加後,再去改變字符串的值),那麼將會違反Set
集合的規則(元素不能重複)。 固然了,上方代碼只是示範做用,String類中沒有value屬性。多線程
###4.安全 String類在Java不少類中被普遍的使用(做爲方法的參數),好比網絡鏈接,打開文件等操做。 若是String類可變,某個鏈接或者文件會可能被改變,這可能會致使嚴重的安全威脅。在反射的時候,不穩定的字符串也可能形成安全問題。 代碼以下:this
boolean connect(string s){ if (!isSecure(s)) { throw new SecurityException(); } //here will cause problem, if s is changed before this by using other references. causeProblem(s); }
###5.不可變的對象是線程安全的 因不可變對象的不能被改變的特性,因此其能夠在多線程中自由的共享。這也消除了進行同步的需求。 總的來講,String被設計成不可變主要是考慮到效率與安全方面。這兩點也是不可變類在不少狀況下更受歡迎的緣由。線程