错误的理解
网上有些人说:字符串不可变是因为其内部保存字符的数组被final修饰了,因此不能改变。
这种说法是错误的,不是因为String类自身,或者其内部value被final修饰而不能被修改。
下面我将浅显易懂的将为什么字符串不可变的知识告诉大家。
图析-文字说明
各位请跟随我的文字说明来看图。
两个final
图上总共出现了两个用紫色框框标记的final,修饰对象的不同导致这两个final的作用各不相同,
-
String类被final修饰,表明该类不能被继承。
-
value被修饰被final修饰,表明value自身的值不能改变,即不能引用其它字符数组, 但是其引用空间中的内容可以修改。
修饰value的final 用紫色线 连接 value[ ] 以及下方的代码片段(用来验证value无法被修改)
String类不可变的原因一
-
大家看向图片右上方的紫色圆弧形框:(但这两个紫色final并不是String不能被修改的真正原因)。
-
以及左下旁的矩形框:(value被修饰被final修饰,表明value自身的值不能改变,即不能引用其它字符数组, 但是其引用空间中的内容可以修改)。引用对象中的内容我画圈了,请注意(比如下方的数组)。
我写了一行String s1 = new String("hello")
的简单代码。其在内存空间中的堆和栈如下所示。
通过地址找到了堆里面的 'hello',这里我画了紫色的竖线,这代表着什么呢?
这代表着这里存的其实并不是我们一开始创建的"hello",而是新建的数组,为的就是给它赋值'hello',所以我画了竖线。而数组是可以修改的,所以final并不是String类不可变的真正原因。
原因一:'hello'作为常量值,存放在常量池中,常量池中的数无法修改。
String类不可变的原因二
图中最左边用红色圆圈框住的private便是原因二,private修饰导致如果我们不重写get和set方法,那么我们将无法获取和修改value的值。而图上代码中确实没有重写get和set方法。
原因二:private修饰,且我们没有重写get和set方法,所以我们无法修改value值。