今天复习java时,突然注意到了一句以前没有注意过的一句话,String 是final修饰的,其值是不可变的。当时看的一脸懵逼,String str = "abc"; str = "abcde"这两行代码没有任何的错误的。上网百度了许久,还是整理下来防止以后忘记吧。
首先要理解的是,string说的不可变是其值不可变,比如String str = "abc",不可变值得是abc不可变,当我们str = “abcde”时,abc没有被销毁,仍然存放在常量池中,只不过是让str指向了“abcde”的内存地址。所以就算不停的赋值,改变的也只是str引用的地址问题,右边的值是不改变的。就举个String类型的引用传递来详细说明下吧
public class Test { public static String appStr(String a){ a += "bbb"; return a; } public static StringBuilder appSb(StringBuilder sb){ sb.append("bbb"); return sb; } public static void main(String[] args) { String s = "aaa"; String s2 = Test.appStr(s); //注意这边打印的是s,不是s2 System.out.println(s); StringBuilder sb = new StringBuilder("aaa"); StringBuilder sb2 = Test.appSb(sb); //注意这边打印的是sb,不是sb2 System.out.println(sb.toString()); } }
上输代码的输出结果是
aaa
aaabbb
下面来分析一下当运行到Test.appStr(s)时,将s(实参)的地址传递给a(形参),此时a="aaa",a+="bbb"之后,a="aaabbb",但是由于string是不可变的,所以在内存上就会重新分配一片内存空间给aaabbb,然后a指向该地址;而s的指向地址却没有发生改变,所以s的值打印出来仍然是aaa;
同理分析StringBuilder,也是引用类型,传递的是地址值,当形参sb传递给实参sb之后,方法对sb进行了修改,sb的值发生了改变(并不像string一样值不可变,重新分配空间),所以运行之后sb的指向值就发生了改变,随后打印的就是aaabbb了。
这样应该就可以理解String的不可变了。
对象一直存在且没有变化,只是指向发生了变换