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);
    }
}

上面的程序输出“真”。两者都是两个不同的标识符/对象,输出如何为“真”?

我的理解是 JVM 将为每个对象创建不同的引用,如果是这样,输出如何是真的?

4

5 回答 5

20

Java 管理一个String文字池。它会尽可能重用这些文字。因此这两个对象实际上是同一个String对象并==返回true。

我相信这被称为字符串实习

于 2009-12-13T10:53:52.957 回答
6

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

如果你要做

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

然后 == 将返回 false 并且 s.equals(t) 将返回 true。

于 2009-12-13T10:54:53.337 回答
5

因为Java 语言规范说:

字符串字面量——或者更一般地,作为常量表达式值的字符串(第 15.28 节)——是“内部的”,以便使用 String.intern 方法共享唯一的实例。

于 2009-12-13T10:54:47.090 回答
5

这是因为编译器执行了内存优化......也就是说,String常量(即 -String由相同的String文字组成)使用相同的String对象,因为Strings它们是不可变的。==操作员只是检查两个对象是否是同一个实际对象。

如果你能抓住 Joshua Bloch 和 Neal Gafter 所著的 Java Puzzlers 一书,并查看第 13 题“动物农场”……他在这个问题上有很好的建议。我要复制一些相关的文字:

“您可能知道类型String的编译时常量是内部的 [JLS 15.28]。换句话说,任何两个String指定相同字符序列的类型常量表达式都由相同的对象引用表示……您的代码应该很少,如果有的话, 依赖于字符串常量的实习。实习只是为了减少虚拟机的内存占用而设计的,而不是作为程序员的工具...比较对象引用时,除非需要,否则应equals优先使用该方法而不是运算符==比较对象身份而不是价值。”

那是来自我提到的上述参考资料……我书中的第 30-31 页。

于 2009-12-13T10:57:51.807 回答
1

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

请注意,上面的文字更多地是对问题的原始状态的强烈建议,因为看起来 OP 不知道幕后发生的实际过程。

其他建议内化的人是对的。为了回答这个问题,我没有足够的时间去看 Java Puzzlers 这本书。我确实怀疑在编译时设置相同的引用,但我也不知道如何找到对它的引用。

于 2009-12-13T10:49:35.380 回答