使用字符串的==运算符 [英] == operator with Strings
问题描述
下面的代码不应该打印Bye,因为==运算符用于比较引用,但奇怪的是,仍然会打印Bye。为什么会这样?我正在使用Netbeans 6.9.1作为IDE。
The code below should not print "Bye", since == operator is used to compare references, but oddly enough, "Bye" is still printed. Why does this happen? I'm using Netbeans 6.9.1 as the IDE.
public class Test {
public static void main(String [] args) {
String test ="Hi";
if(test=="Hi"){
System.out.println("Bye");
}
}
}
推荐答案
此行为是因为实习。该行为在 <$ c $的文档中有所描述。 c> String #intern (包括为什么它出现在您的代码中,即使您从未调用 String #intern
):
This behavior is because of interning. The behavior is described in the docs for String#intern
(including why it's showing up in your code even though you never call String#intern
):
字符串池(最初为空)由类
String
私有维护。
当调用实习生
方法时,如果池已包含等于此的字符串字符串
由 equals(Object)
方法确定的对象,然后返回池中的字符串。否则,将此 String
对象添加到池中,并返回对此 String
对象的引用。
When the intern
method is invoked, if the pool already contains a string equal to this String
object as determined by the equals(Object)
method, then the string from the pool is returned. Otherwise, this String
object is added to the pool and a reference to this String
object is returned.
对于任何两个字符串 s
和 t
, s.intern()== t.intern()
是 true
当且仅当 s时。 equals(t)
为真。
It follows that for any two strings s
and t
, s.intern() == t.intern()
is true
if and only if s.equals(t)
is true.
所有文字字符串和字符串值常量表达式都是实体。字符串文字在 Java语言规范的§3.10.5中定义。
All literal strings and string-valued constant expressions are interned. String literals are defined in §3.10.5 of the Java Language Specification.
例如:
public class Test {
private String s1 = "Hi";
public static void main(String [] args) {
new Test().test();
System.exit(0);
}
public void test() {
String s2 ="Hi";
String s3;
System.out.println("[statics] s2 == s1? " + (s2 == s1));
s3 = "H" + part2();
System.out.println("[before interning] s3 == s1? " + (s3 == s1));
s3 = s3.intern();
System.out.println("[after interning] s3 == s1? " + (s3 == s1));
System.exit(0);
}
protected String part2() {
return "i";
}
}
输出:
[statics] s2 == s1? true
[before interning] s3 == s1? false
[after interning] s3 == s1? true
走过:
- 分配给<的文字code> s1 会自动实习,因此
s1
最终会引用池中的字符串。 - 分配给
s2
的文字也是自动实习的,因此s2
最终指向同一个实例s1
指向。这很好,即使代码的两位代码可能彼此完全不知道,因为Java的String
实例是不可变的。你无法改变它们。您可以使用toLowerCase
之类的方法来获取带有更改的 new 字符串,但原来您调用toLowerCase
(等)保持不变。所以它们可以安全地在不相关的代码中共享。 - 我们通过运行时创建 new <$ c> c> String 实例操作。即使新实例与实际实例具有相同的字符序列,它也是单独的实例。运行时不会自动生成动态创建的字符串,因为涉及成本:在池中查找字符串的工作。 (编译时,编译器可以将成本转嫁给自己。)现在我们有两个实例,一个是
s1
和s2
指向,并且s3
指向。所以代码显示s3!= s1
。 - 然后我们明确实习生
s3
。也许这是我们计划长期坚持的大字符串,我们认为它可能会在其他地方重复。因此,我们接受实习的工作,以换取潜在的内存节省。由于根据定义实习意味着我们可能会返回一个新的参考,我们将结果分配回s3
。 - 我们可以看到实际上,
s3
现在指向同一个实例s1
和s2
指向。
- The literal assigned to
s1
is automatically interned, sos1
ends up referring to a string in the pool. - The literal assigned to
s2
is also auto-interned, and sos2
ends up pointing to the same instances1
points to. This is fine even though the two bits of code may be completely unknown to each other, because Java'sString
instances are immutable. You can't change them. You can use methods liketoLowerCase
to get back a new string with changes, but the original you calledtoLowerCase
(etc.) on remains unchanged. So they can safely be shared amongst unrelated code. - We create a new
String
instance via a runtime operation. Even though the new instance has the same sequence of characters as the interned one, it's a separate instance. The runtime doesn't intern dynamically-created strings automatically, because there's a cost involved: The work of finding the string in the pool. (Whereas when compiling, the compiler can take that cost onto itself.) So now we have two instances, the ones1
ands2
point to, and the ones3
points to. So the code shows thats3 != s1
. - Then we explicitly intern
s3
. Perhaps it's a large string we're planning to hold onto for a long time, and we think it's likely that it's going to be duplicated in other places. So we accept the work of interning it in return for the potential memory savings. Since interning by definition means we may get back a new reference, we assign the result back tos3
. - And we can see that indeed,
s3
now points to the same instances1
ands2
point to.
这篇关于使用字符串的==运算符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!