String p = "12";
这行代码创建一个名为p的字符串变量,并将字符串常量"12"赋值给它。在常量池中已经存在"12"这个字符串,所以变量p指向常量池中"12"的地址。
String c = "1" + "2";
这行代码将字符串常量"1"和"2"进行拼接,生成新的字符串"12"。由于编译器会对字符串常量进行优化,这里实际上只创建了一个String对象,这里的变量c指向的地址为常量池中"12"的地址
String o = "1";
这行代码创建一个名为o的字符串变量,并将字符串常量"1"赋值给它。在常量池中已经存在"1"这个字符串,所以变量o将引用常量池中的这个字符串
String s = "2";
这行代码创建一个名为s的字符串变量,并将字符串常量"2"赋值给它。在常量池中已经存在"2"这个字符串,所以变量s将引用常量池中的这个字符串。
String m = o + s;
这行代码将变量o和变量s进行拼接,生成新的字符串"12"。在运行时,由于涉及到变量的拼接,会创建一个新的String对象来存储拼接后的结果,这里不会涉及到常量池
System.out.println(m == p);//false
在Java中,字符串是不可变的,即一旦创建就不能更改。当我们使用字符串连接操作符(+)连接两个字符串时,会创建一个新的字符串对象。在这个例子中,变量m通过将变量o和s连接起来创建了一个新的字符串对象。尽管m的值与p相同,但它们是不同的对象,因此m == p的比较结果为false。
String s1 = new String("12")
JVM会在堆内存中创建一个新的字符串对象,并将值为"12"的字符串复制到这个对象中,然后将引用赋值给s1。这种方式会在堆内存中创建一个新的对象,即使有相同的字符串已经存在于常量池中
System.out.println(s1 == p);//false
s1使用new关键字创建了一个新的String对象,所以它在堆中分配了新的内存空间。而p是直接在字符串常量池中创建的String对象。所以s1 == p的结果为false
String s1 = new String("13");
s1 = "12";
Java中的String是不可变的,即一旦创建,其值就不能被修改。所以当我们将s1的引用指向"12"时,实际上是创建了一个新的String对象"12",而不是修改原来的"13"对象。
所以最终,s1的值为"12",而"13"这个String对象被垃圾回收器回收。
此时System.out.println(s1 == p);//true此时s1地址重新指向常量池中的"12"
String s2 = String.valueOf("12");
String.valueOf方法创建了一个String对象s2,其值也为"12"。String.valueOf方法会将给定的参数转换为字符串形式,并返回一个新的String对象。在这里,"12"已经是一个字符串,所以String.valueOf("12")会直接返回一个指向字符串常量池中"12"的引用。
最后附上一张肥伦的表情包,气鼓鼓