字符串的不可变性:
String类内部定义了 final char[ ] value ;数组用于存储字符串数据。
这里的value数组是通过final关键字修饰的,也就说字符串其实是一个常量,一旦在内存中申请出一个空间并且为其赋值之后这个空间中的字符串值就不可以修改了,将这个性质我们称之为不可变性。
有人认为String的不可变性是因为String是被final修饰的 ,final修饰类时表示该类不可以被继承,而final修饰属性的时候,表示的是该属性不可以被更改。
因此字符串的不可改变其实应该理解为不可以直接改变或者不可以操作字符串去改变自己的初始的字符存储数组,字符串本身是不可修改的,他的改动是建立在新new出一个string对象,然后生成新的Char[ ] value数组来完成的。
今天遇见一道经典的面试题,让大家了解一下字符串不可变。
代码如下:
String s1 = new String("aaa");
String s2 ="aaa";
String s3 ="aaa";
string s3 =s2;
s1是通过new一个对象创建的,它是在堆中另开辟一个新空间,JVM首先会对这个字面量(aaa)进行检查,如果字符串常量池中存在相同内容的字符串对象的引用,则将这个引用返回,否则新的字符串对象被创建,然后将这个引用放入字符串常量池。
s2存放的是aaa这个值的地址,s2放在栈里边,对象s2指向abc的地址。
特别的,当 String s2 = "aaa"时,对象会创建在字符串常量池中,而字符串常量池是堆中的一个特殊区域(字符串池不会维护相同的字符数组),意思就是字符串池中只有一个aaa,而s2和s3对象的值都是aaa,所以它们两个只能输出一个值。
对s3来说,就是s3只拷贝了s2的地址,并没有拷贝s2的值。
原因总结
- 字符串本质是数组,数组在创建时就开辟了一个连续地址,固定的空间的内存
- 字符串常量池实现的前提条件是Java中String对象是不可变的,字符串的值存放在字符串常量池中。