下面的代码不应该打印"Bye",因为==运算符用于比较引用,但奇怪的是,仍然会打印"Bye".为什么会这样?我使用Netbeans 6.9.1作为IDE.
public class Test {
public static void main(String [] args) {
String test ="Hi";
if(test=="Hi"){
System.out.println("Bye");
}
}
}
Run Code Online (Sandbox Code Playgroud)
T.J*_*der 42
这种行为是因为实习.该行为在文档中描述String#intern(包括为什么它会在您的代码中显示,即使您从未调用过String#intern):
最初为空的字符串池由类私有维护
String.当
intern被调用的方法,如果池已经包含一个字符串等于该String由测定对象equals(Object)的方法,然后从池中字符串被返回.否则,将此String对象添加到池中,并String返回对此对象的引用.它遵循对于任何两个字符串
s和t,s.intern() == t.intern()是true当且仅当s.equals(t)是真实的.所有文字字符串和字符串值常量表达式都是实体.字符串文字在Java语言规范的 §3.10.5中定义.
例如:
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";
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
[statics] s2 == s1? true [before interning] s3 == s1? false [after interning] s3 == s1? true
走过那个:
s1会自动实现,因此s1最终会引用池中的字符串.s2也是自动实习的,因此s2最终指向相同的实例s1指向.这很好,即使代码的两位代码可能彼此完全不知道,因为Java的String实例是不可变的.你无法改变它们.您可以使用类似的方法toLowerCase来获取带有更改的新字符串,但您调用的原始字符toLowerCase(等)保持不变.因此,他们可以安全地在不相关的代码之间共享.String实例.尽管新实例具有与实例相同的字符序列,但它是一个单独的实例.运行时不会自动动态创建字符串,因为涉及成本:在池中查找字符串的工作.(编译时然而,编译器可以采取的成本转嫁给了自己.)所以,现在我们有两个例子,一个s1和s2点,和一个s3点.所以代码显示了这一点s3 != s1.s3.也许这是我们计划长期坚持的大字符串,我们认为它可能会在其他地方重复出现.因此,我们接受实习的工作,以换取潜在的内存节省.由于按定义实习意味着我们可能会返回一个新的引用,我们将结果返回给s3.s3现在指向同一个实例s1并s2指向.Boh*_*ian 10
硬编码字符串被编译到JVM的字符串表中,字符串表包含唯一的字符串 - 即编译器只存储一个"Hi"的副本,因此您正在比较同一个对象,因此==有效.
如果你实际使用构造函数创建一个新的String,比如new String("Hi"),你会得到一个不同的对象.
| 归档时间: |
|
| 查看次数: |
1170 次 |
| 最近记录: |