我记得在Bloch的 Effective Java 中阅读了一节,其中说大多数情况下,
String a = "fish";
String b = "fish";
在大多数情况下a == b因为字符串是不可变的。但是由于临时构造对象或其他类似的东西,新的String(“fish”)会产生一个独特的对象引用。
我浏览了Bloch关于equals(),不变性和对象创建的章节,但是我记得找不到这一点!撕掉我的头发,有没有人记得这是什么原因的描述?它甚至可能不在 EJ 中,但我想找到它。提示:这解释的是我的实际问题。
答案 0 :(得分:10)
这与不变性无关。这是JVM处理字符串的方式。具有相同内容的字符串文字表示相同的对象(“字符串文字”大致意味着“用引号括起来的文本”)。 JVM中有一个字符串对象表,每个字符串文字在该表中只有一个对象。
但是,当您明确地创建新实例时,您将根据从表中获取的字符串对象构造一个新的字符串对象。
从不使用文字形成的任何字符串(但通过调用toString(),通过实例化等),您可以通过调用str.intern()
从jvm表中获取对象。 intern()
方法只返回存在的每个字符序列的一个实例。 new String("fish").intern()
将返回与String s = "fish"
要记住两件事:
new String("something")
equals(..)
进行比较(除非您确实知道自己在做什么,并将其记录下来)答案 1 :(得分:0)
我认为您正在寻找维护常量字符串池的String.intern()方法。
运算符'=='比较对象引用(地址),而.equals()是一个查看语义等价的方法调用。
编译器将查看String a =“fish”和String b =“fish”,然后可能会或可能不会指向同一地址。但是,如果你做a.intern(); b.intern()然后它可能会将它们放在同一个字符串池中并且== b。
答案 2 :(得分:0)
如果您正在寻找明确的描述,请转到定义:JLS § 3.10.5 String Literals。
您应该熟悉的示例代码是,
因此,测试程序由编译单元(第7.3节)组成:
package testPackage; class Test { public static void main(String[] args) { String hello = "Hello", lo = "lo"; System.out.print((hello == "Hello") + " "); System.out.print((Other.hello == hello) + " "); System.out.print((other.Other.hello == hello) + " "); System.out.print((hello == ("Hel"+"lo")) + " "); System.out.print((hello == ("Hel"+lo)) + " "); System.out.println(hello == ("Hel"+lo).intern()); } } class Other { static String hello = "Hello"; }
和编译单元:
package other; public class Other { static String hello = "Hello"; }
产生输出:
true true true true false true