在Java中String類為什么要設計成final?String真的不可變嗎?其他基本類型的包裝類也是不可變的嗎?


最近突然被問到String為什么被設計為不可變,當時有點懵,這個問題一直像bug一樣存在,竟然沒有發現,沒有思考到,在此總結一下。

1.String的不可變
String類被final修飾,是不可繼承和修改的。當一個String變量被第二次賦值時,不是在原有內存地址上修改數據,而是在內存中重新開辟一塊內存地址,並指向新地址。

String類為什么要被設計為是final的?

  1.不可變性支持線程安全
  2.不可變性支持字符串常量池,提升性能
  3.String字符串作為最常用數據類型之一,不可變防止了隨意修改,保證了數據的安全性

正常情況下Java的String字符串是final且不可變的。不過可以通過特殊手段修改它的內容。
String類的主力成員字段value是個char[ ]數組,而且是用final修飾的。final修飾的字段創建以后就不可改變。因為雖然value是不可變,也只是value這個引用地址不可變。擋不住Array數組是可變的事實。Array的數據結構看下圖:

也就是說Array變量只是stack上的一個引用,數組的本體結構在heap堆。String類里的value用final修飾,只是說stack里的這個叫value的引用地址不可變。沒有說堆里array本身數據不可變。

代碼測試:

 1 String test = "immutable String";
 2 String test1 = test;
 3 String test2 = new String(test);
 4 String test3 = new String(test.toCharArray());
 5 Field values = String.class.getDeclaredField("value");
 6 values.setAccessible(true);
 7 char[] chars = (char[])values.get(test);
 8 chars[0] = 'u';
 9 chars[1] = 'n';
10 System.out.println("test==test1:" + (test == test1));
11 System.out.println("test==test2:" + (test == test2));
12 System.out.println("test1==test2:" + (test1 == test2));
13 System.out.println("test:" + test + "   test1:" + test1 + " test2:" + test2 + "  test3:" + test3);

由String的不可變性引申到其他基本數據類型: Byte,Short,Integer,Long,Double,Float,Character,Boolean 八種基本數據的包裝類,仔細查看發現也是final修飾的,再仔細查看一下enum枚舉類型,發現用javac編譯后再用javap反編譯也是被編譯為final修飾的類,並且其枚舉值全部定義為static final 修飾的成員變量。

由此發現,Java設計者在設計Java基本數據類型時,把基本數據類型全部設計為不可變的,這樣既方便了開發人員,又保證了數據的安全性。

總結:Java中String是不可變的,但是可以通過反射修改其內容

備注:
作者:Shengming Zeng
博客:http://www.cnblogs.com/zengming/ 

本文是原創,歡迎大家轉載;但轉載時必須注明文章來源,且在文章開頭明顯處給明鏈接。
<歡迎有不同想法或見解的同學一起探討,共同進步>


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM