1.什么是不可变?

image.png
[图片上传中...(image.png-57137f-1653059235638-0)]
为什么String是不可变得呢?
public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
/** String本质是个char数组. 而且用final关键字修饰.*/
private final char value[];
...
...
}
String类final进行修饰,value数组final修饰,使得String无法继承,value是无法进行更改的,但是这里的更改指的是stack中的value的引用地址是不能发生改变的,但是Array数组是可变的,就是我们的堆之中的数据是可以改变的,这样当我们的数据进行改变之后,其实产生了一个新的对象、新的地址,但是原来的value的应用的对象个地址是没有发生改变的,我们可以用一个新的引用来获取到这个新的地址、新的对象
比如:
class Test{
//不可变的String
public static String appendStr(String s){
s+="bbb";
return s;
}
//可变的StringBuilder
public static StringBuilder appendSb(StringBuilder sb){
return sb.append("bbb");
}
public static void main(String[] args){
//String做参数
String s=new String("aaa");
String ns=Test.appendStr(s);
System.out.println("String aaa >>> "+s.toString());
//StringBuilder做参数
StringBuilder sb=new StringBuilder("aaa");
StringBuilder nsb=Test.appendSb(sb);
System.out.println("StringBuilder aaa >>> "+sb.toString());
}
}
//Output:
//String aaa >>> aaa
//StringBuilder aaa >>> aaabbb
其中我们发现s是不可变,ns就是我们的新的引用。
好处:安全
拿hashSet举例,我们知道HashSet其中的键值是存在唯一性的,当我们使用Stringbulider来进行存储,也就是字符串可变,那么当我们向HashSet中加入多个StringBuilder键值的时候,存在一个问题就是,后续若是我们将StringBuilder的值进行更改,若是使得其中的两个键值相等,这样就会破坏Hashset的唯一性,
常量池属性:
相同的String常量指向同一个内存地址

image.png
这样在大量使用字符串的情况下,可以节省内存空间,提高效率。但之所以能实现这个特性,String的不可变性是最基本的一个必要条件。要是内存里字符串内容能改来改去,这么做就完全没有意义了。