基本Java问题:字符串相等

nov*_*ice 5 java string equality

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

以上程序输出"true".两者是两个不同的标识符/对象输出是如何"真"?

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

Nei*_*ley 20

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

我相信这叫做字符串实习

  • 请随便请...我的答案指出......不要依赖这个事实.当你的意思是:-)时,请使用`equals`.当人们发布关于字符串实习的事情时,我总是感到紧张...显然答案是正确的,我不反对,但我想强调的是,虽然它解释了答案,但它不应该是依赖(正如Josh Bloch指出的那样,它是一个实现细节,而不是程序员的工具). (4认同)
  • 语言规范中强制要求的东西很难和实现细节,但我同意:虽然你可以依赖于被实习的文字,但你不应该依赖于你使用的文字字符串 - 这很容易改变. (2认同)

Jef*_*ter 6

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

如果你这样做的话

String s = new String("foo");
String t = new String("foo");
Run Code Online (Sandbox Code Playgroud)

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


Mic*_*rdt 5

因为Java语言规范说:

字符串文字 - 或者更一般地说,作为常量表达式(第15.28节)的值的字符串 - 是"实例化"以便使用String.intern方法共享唯一实例.


Tom*_*Tom 5

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

如果你能抓住Joshua Bloch和Neal Gafter的Java Puzzlers这本书,看一下拼图13,"动物农场"......他对这个问题有很好的建议.我要复制一些相关的文字:

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

这是我在上面提到的参考资料......在我的书中的第30-31页.