我知道“ ==”比较引用,并且java字符串是不可变的,并且使用字符串池缓存,但是在这个示例中我仍然感到困惑:
final String fName = "James";
String lName = "Gosling";
String name1 = fName + lName;
String name2 = fName + "Gosling";
String name3 = "James" + "Gosling";
System.out.println(name1 == name2); // 1
System.out.println(name2 == name3);
这给了我结果:
false
true
我仍然感到困惑,为什么System.out.println(name1 == name2);给我一个错误,因为我知道两个值都应该缓存在字符串池中?
由于fName
是最终的并使用文字字符串初始化,因此它是一个常量表达式。
所以指令
String name2 = fName + "Gosling"
编译为
String name2 = "James" + "Gosling"
被编译为
String name2 = "JamesGosling"
因此,在字节码中,您具有等价于
String name2 = "JamesGosling";
String name3 = "JamesGosling";
因此,name2和name3都引用了相同的文字字符串,该字符串已被嵌入。
另一方面,lName
不是最终的,因此不是常量表达式,并且串联发生在运行时而不是编译时。因此,串联将创建一个新的,未插入的String。
创建两个具有相同字符串值的字符串并不能保证它们都来自字符串池。您需要调用s.intern()
以确保从字符串池中获得的字符串具有相同的值和内存地址。
[连接很有可能导致将String读取为String对象,而不是String文字。这是由于编译器不知道s.intern()
是否会产生文字。如果它是字符串文字,则转到字符串池。如果它是一个字符串对象,则不能保证它会进入字符串池并像其他任何对象一样被对待。