如何理解java中String的不可变性
生活随笔
收集整理的這篇文章主要介紹了
如何理解java中String的不可变性
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
文章目錄
- 問題
- String類的聲明
- final關(guān)鍵字的作用
- String的不變性
- String的不變性有哪些好處
- String真的是絕對不可變嗎
問題
為什么大家都在說String是不可變的?
String類的聲明
public final class Stringimplements java.io.Serializable, Comparable<String>, CharSequence {/** The value is used for character storage. */private final char value[];......public String(char value[]) {this.value = Arrays.copyOf(value, value.length);}java中String聲明是final類型,說明String不可繼承,String里面核心存儲值的value是一個char[]數(shù)組也使用了final修飾,說明value的引用地址是不改變。
final關(guān)鍵字的作用
使用final修飾的變量,編譯器不允許我們做修改的,舉例說明:
@Testpublic void finalTest(){final char[] value = {'a','a','a'};char[] value2 = {'b','b','b'};value = value2;//cannot assign a value to final variable}上面value = value2這一行會報錯,無法為final修飾的變量賦值,意思就是使用final修飾的變量的引用不能被更改。但是引用不能被更改不代表不能改變里面的值。如下說所示:
@Testpublic void finalTest() {final char[] value = {'a', 'a', 'a'};System.out.println(value);value[2] = 'b';//將索引位置為2的修改為bSystem.out.println(value);}打印結(jié)果:
aaa aabString的不變性
這里簡單的例子測試一下String的不可變性
@Testpublic void testString() {String test1 = new String("aaa");StringBuilder test2 = new StringBuilder("aaa");System.out.println("輸出原始的test1:" + test1);System.out.println("輸出原始的test2:" + test2.toString());//追加字符串之后String afaddStr = addString(test1);StringBuilder afaddStrBuild = addStringBuilder(test2);System.out.println("輸出原始的test1:" + test1);System.out.println("輸出原始的test2:" + test2.toString());}/*** 向字符串中添加bbb** @param str*/public String addString(String str) {str = str + "bbb";return str;}/*** 向字符串中追加bbb** @param str*/public StringBuilder addStringBuilder(StringBuilder str) {str.append("bbb");return str;}結(jié)果輸出:
輸出原始的test1:aaa 輸出原始的test2:aaa 輸出原始的test1:aaa 輸出原始的test2:aaabbbtest1在一頓操作之后還保留了原來的樣子,但是test2已經(jīng)被改變了,其實String這種不可變性我們經(jīng)常無意間使用,最常見的使用場景就是HashSet的值。看如下示例:
@Testpublic void testString2() {String key1 = new String("aaa");StringBuilder key2 = new StringBuilder("aaa");HashSet set = new HashSet<>();set.add(key1);set.add(key2);System.out.println("原始存儲的set值:"+ set.toString());/**************模擬業(yè)務操作******************/String afaddStr = addString(key1);StringBuilder afaddStrBuild = addStringBuilder(key2);/**************模擬業(yè)務操作****end***********/System.out.println("業(yè)務執(zhí)行后set值:"+ set.toString());}/*** 向字符串中添加bbb** @param str*/public String addString(String str) {str = str + "bbb";return str;}/*** 向字符串中追加bbb** @param str*/public StringBuilder addStringBuilder(StringBuilder str) {str.append("bbb");return str;}如果使用StringBuilder存儲則我們無意間的業(yè)務操作會改變Set中的值,這可能引起不必要的麻煩。
String的不變性有哪些好處
String真的是絕對不可變嗎
看如下例子:
@Testpublic void testString3() throws IllegalAccessException, NoSuchFieldException {String strObj = new String("aaa");System.out.println("反射執(zhí)行前字符串:" + strObj);System.out.println("反射執(zhí)行前的hash值:" + strObj.hashCode());Field field = strObj.getClass().getDeclaredField("value");field.setAccessible(true);char[] value = (char[]) field.get(strObj);value[2] = 'b';System.out.println("反射執(zhí)行后字符串:" + strObj);System.out.println("反射執(zhí)行后的hash值:" + strObj.hashCode());}打印結(jié)果如下:
反射執(zhí)行前字符串:aaa 反射執(zhí)行前的hash值:96321 反射執(zhí)行后字符串:aab 反射執(zhí)行后的hash值:96321說明通過反射我們是可以修改String的值的
參考如下:
https://www.zhihu.com/question/20618891
總結(jié)
以上是生活随笔為你收集整理的如何理解java中String的不可变性的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JavaScript的常用工具汇总
- 下一篇: J.U.C系列(一)CountDownL