为什么说String是不可变的

来源:互联网 发布:代理商授权书php源码 编辑:程序博客网 时间:2024/04/29 19:31

1.什么是不可变?

简单的例子:
String s1= “abc”;
String s1=s1;
s1= “def”;
此时s1变化了吗?变了!s1的地址从指向 “abc”变成指向 “def”;
重要的不在这里,内存上的“abc”本身并没有被改变!指向 “abc”的s2也没有被改变

2.怎么做到的?

两个final ,一个在String的类修饰符,一个是String内部保存数据的数组value的变量修饰符
public final class String
private final char value[];

String类是用final关键字修饰,这说明String不可继承。

实质上用以保存内容的属性value 的定义 final char[],final修饰的字段创建以后就不可改变,这里指的是引用的地址将不可以再变

但是现在来看问题并没有解决,String本身依旧是可变的,虽然引用地址不再能变化,但是数组本身的内容还是可以变化的

也就是说Array变量只是stack上的一个引用,数据的本体结构在heap堆。String类里的value用final修饰,只是说stack里的这个叫value的引用地址不可变。没有说堆里array本身数据不可变。看这个这个例子

所以看来,String 不可变并不是因为两个final

为什么要这么做?

简单来说这是作为字面量的个人修养
回看第一部分,s2并没有被改变,这正是作为字面量的意义的体现!
没有这个特性,任何语言的基础都将不复存在,因为你无法保证你存的内容是不会被其他线程或者其他的不想管的操作所影响。
另外,考虑到字符串池本身存在的意义正式让大量存在大量使用的字符串不会被重复的创建销毁,因为在系统级别看来,这种对性能的损耗是不可接受的

结论

String的不可变还是要结合堆来看,他的不可变是字符串池里的对象不可变,而不是我们创建的String不可变

eg:补充一下
还有一些问题是相关的
比如String s1=new String(“abc”);这个过程创建了几个对象?
之前没有创建过,则创建两个对象 一个在堆 一个在PermGen常量池

原创粉丝点击