Java字符串两种声明方式在堆内存中不同的体现
字符串池
String不可变是因为在JDK中String类被声明为一个final类,且类内部的value字节数组也是final的,只有当字符串是不可变时字符串池才有可能实现,字符串池的实现可以在运行时节约很多heap空间,因为不同的字符串变量都指向池中的同一个字符串。
string1 = "100" 和 new String("100")
public class Test {
public static void main(String[] args) {
String string1 = "100";
String string2 = "100";
// true
System.out.println(string1 == string2);
// 'new String("100")' is redundant
String string3 = new String("100");
String string4 = new String("100");
// false
System.out.println(string3 == string4);
}
}
当代码执行到String s1 = "100"时,会先看常量池里有没有字符串刚好是“100”这个对象,如果没有,在常量池里创建初始化该对象,并把引用指向它,如下图,绿色部分为常量池,存在于堆内存中:
当执行到String s2 = "100"时,发现常量池已经有了100这个值,于是不再在常量池中创建这个对象,而是把引用直接指向了该对象:
这时候打印System.out.println(s1 == s2)时,由于==是判断两个对象是否指向同一个引用,所以这儿打印出来的就应该是true。
继续执行到Strings3 = new String("100")这时候我们加了一个new关键字,这个关键字呢就是告诉JVM,你直接在堆内存里开辟一块新的内存:
继续执行String s4 = new String("100"):
这时候再打印System.out.println(s3 == s4)那一定便是false了,因为s3和s4不是指向对一个引用(对象)。
我们在写代码过程中,为了避免重复的创建对象,尽量使用String s1 ="123"而不是String s1 = new String("123"),因为JVM对前者给做了优化。

浙公网安备 33010602011771号