2009-12-13 61 views
5
public class A { 

    static String s1 = "I am A"; 

    public static void main(String[] args) { 
     String s2 = "I am A"; 
     System.out.println(s1 == s2); 
    } 
} 

上面的程序输出 “真”。两者都是两个不同的标识符/对象输出是如何“真”的?基本的Java问题:字符串平等

我的理解是,JVM会为每个对象不同的参考,如果输出是那么如何正确的?

回答

20

的Java管理一个String文字池。它可以重用这些文字。因此这两个对象实际上是相同的String对象,并且==返回true。

我相信这就是所谓的string interning

+1

有关字符串池的信息,请查看维基百科:http://en.wikipedia.org/wiki/String_interning(+1同一想法) – 2009-12-13 10:55:17

+1

是的,字符串文字会根据实习方法API - http ://java.sun.com/javase/6/docs/api/java/lang/String.html – Ash 2009-12-13 10:55:39

+1

这不仅仅是文字,也是编译时常量。 – 2009-12-13 10:59:25

1

你是不是比较字符串的内容。你只是比较对象的引用。你应该使用equal方法(它是String类的成员)。无论是或者你可以使用compareTo方法(也在同一个String类下)来检查返回值是否为零。

请注意上面的文字更强烈建议对问题的原单状态,它出现在OP不知道实际过程会在幕后的。

其他的人暗示internalling是正确的。为了回答这个问题,我没有足够的时间去看Java Puzzlers书籍。我确实怀疑在编译时设置了相同的引用,但我不知道如何找到这个引用。

+0

如果我比较的内容那么答案肯定是‘真’,但这里都是两个不同的变量,赢得't jvm创建两个不同的引用? – novice 2009-12-13 10:52:27

+1

@Felix。不,他正在比较引用,并且输出是真实的 - 这正是引发此问题的稍微令人惊讶的结果。 – 2009-12-13 10:56:56

+2

正确答案? – 2009-12-13 10:57:54

5

因为Java Language Specification说:

字符串文字,或者更一般地说, 字符串是 常量表达式(§15.28)值-are “interned”,以便使用方法 String.intern共享唯一的 实例。

6

==检查变量是否指向完全相同的对象实例。您创建的两个字符串文字指向内存中的相同位置,因此它们是相同的。字符串文字是实现的,所以相同的字符串文字是内存中的同一个对象。

如果你是做

String s = new String("foo"); 
String t = new String("foo"); 

然后==将返回false和s.equals(T)将返回true。

5

这是因为由编译器执行的内存优化...即String常数(即 - 由同一String字面做出String S)使用相同的String对象,因为Strings是不可改变的。 ==运算符只检查两个对象是否是相同的实际对象。

如果您可以通过Joshua Bloch和Neal Gafter抓住Java Puzzlers书籍,并看看拼图13“动物农场”......他在这个问题上有很好的建议。我会复制一些相关的文字:

“你可能知道String类型是编译时常被拘留[JLS 15.28]换句话说String类型的用于指定相同的字符序列的任意两个常量表达式。由相同的对象引用表示...你的代码应该很少,如果有的话,取决于字符串常量的实习。实际内部设计仅用于减少虚拟机的内存占用量,而不是程序员的工具...在比较对象引用时,应优先使用equals方法,而不要使用==运算符,除非需要比较对象标识而不是值。”

从上述参考我提到......第30页的 - 。31在我的书

+1

我提到这个[我没有提到它为什么这么做],我已经被拒绝了。 – monksy 2009-12-13 11:00:03

+0

+1提到Puzzlers并解释原因 – monksy 2009-12-13 11:15:08