0

是在做:

String a = new String();
String b = a;

并做:

String a = new String();
String b = a.intern();

是一样的吗?

实际上,如果我测试,参考都是一样的:

String a = new String("te");
String b = a.intern();
String c = a;
String d = "t" + "e";
System.out.print(a.equals(b));
System.out.print(b.equals(c));
System.out.print(a.equals(d));

因为字符串将永远在字符串池中?

4

4 回答 4

5

您的equals测试没有检查引用- 他们正在检查字符串相等性。您应该使用==来检查身份的引用。实际上,您犯了常见的菜鸟 Java 错误——通常人们==在应该使用equals. 在这种特殊情况下,所有这些都将 print false,因为涉及两个 String 对象(来自常量池的字符串和在第一行中创建的新字符串)。如果我们分别称它们为 #1 和 #2,我们最终会得到:

a = #2 // Explicit call to string constructor
b = #1 // intern will return reference to constant pool instance
c = #2 // Direct assignment
d = #1 // Equivalent string constant, so reference to constant pool instance

但是,您可能会觉得这很有趣:

String a = "te";
String b = a.intern();
String c = "t" + "e";
System.out.println(a == b); // true
System.out.println(a == c); // true

"te"and"t" + "e"是相等的常量字符串表达式,所以最终作为对单个字符串的引用,并且调用intern已经在文字池中的字符串不会有任何效果。

于 2011-12-17T23:15:20.047 回答
1

首先:"t" + "e"是一个字符串文字,因为它会被编译器优化。此字符串文字也用于此行:

String a = new String("te");

现在,String(String)构造函数制作了 String 的物理副本。所以,这意味着 ad不是同一个对象。

然后:String.equals(String) 比较两个字符串。它表示内容是否相等而不是对象。这意味着您可能有两个不同的 String 对象,它们具有相同的字符序列,这将产生String.equals(String)return true

String.intern()将字符串放入字符串池中,如果它还没有的话。但是这种方法不能改变对象本身。所以这个代码示例将打印错误:

String literal = "lit";
String nonLiteral = "abclit".substring(3); // equals "lit"
nonLiteral.intern(); // "lit" was already in the String pool
                     // but `nonLiteral` is still `nonLiteral`
System.out.println(literal == nonLiteral); // false

但是,如果您这样做:它将返回 true:

String literal = "lit";
String nonLiteral = "abclit".substring(3); // equals "lit"
nonLiteral = nonLiteral.intern(); // "lit" was already in the String pool and
                                  // it will return the object `literal`.
                                  // Now the value is replaced.
System.out.println(literal == nonLiteral); // true
于 2011-12-17T23:27:19.750 回答
0

使用 equals 不会测试引用的相等性。它测试字符串内容的相等性。您需要使用==来测试引用的相等性。

回答你的问题,不,不一样。第一个片段将两个引用(a 和 b)分配给同一个字符串。第二个创建一个字符串,将其分配给a,然后实习该字符串并将实习池返回的字符串分配给b。因此 a 和 b 可以引用两个不同的 String 实例(当然会,因为空字符串肯定在池中,因此 intern() 不会返回 a 引用的字符串,但会返回池化的空字符串)

于 2011-12-17T23:15:44.093 回答
0

如果该字符串值已经从不同的String实例中实习,intern()将返回较早的实例。

于 2011-12-17T23:16:01.317 回答