0

我记得读过一段,可能在 Bloch 的Effective Java中,说在大多数情况下,

String a = "fish";
String b = "fish";

在大多数情况下 a == b 因为字符串是不可变的。但是由于对象的临时构造或类似的构造, new String("fish") 会产生一个不同的对象引用。

我浏览了有关 equals()、不变性和对象创建的 Bloch 章节,但找不到我记得的这一点!扯掉我的头发,有人记得这是为什么的描述吗?它甚至可能不在EJ中,但我想找到它。提示:这在哪里解释是我的实际问题。

4

3 回答 3

10

它与不变性无关。这是 JVM 处理字符串的方式。具有相同内容的字符串字面量表示相同的对象(“字符串字面量”大致意思是“用引号括起来的文本”)。JVM 中有一个字符串对象表,每个字符串字面量在该表中只有一个对象。

但是,当您显式创建一个新实例时,您会根据从表中获取的字符串对象构造一个新的字符串对象。

从不使用文字(但通过调用 toString()、通过实例化等)形成的任何字符串中,您可以通过调用从 jvm 表中获取对象str.intern()。该intern()方法为每个存在的字符序列返回一个实例。new String("fish").intern()将返回相同的实例String s = "fish"

有两件事要记住:

  • 从不使用new String("something")
  • 总是比较字符串equals(..)(除非你真的知道你在做什么,并记录下来)
于 2011-10-20T21:42:28.447 回答
0

我认为您正在寻找维护恒定字符串池的String.intern()方法。

运算符 '==' 比较对象引用(地址),而 .equals() 是查看语义等价的方法调用。

编译器将查看 String a = "fish" 和 String b = "fish",然后可能会或可能不会指向相同的地址。但是,如果您执行 a.intern(); b.intern() 那么它可能会将它们放在同一个字符串池和 a == b 中。

于 2011-10-20T21:46:17.473 回答
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
于 2011-10-20T23:54:56.810 回答