1

可能重复:
如何比较 Java 中的字符串?
演示与 Java 的字符串比较

我对这里的基础知识感到困惑。自从我开始使用 java 以来,我总是被告知“不要使用 == 进行字符串比较;总是使用 equals”。现在我已经开始为 OCJP 学习并遇到了一些令人困惑的问题。

1)

String s1 = "Monday"; 
String s2 = "Monday";

s1 == s2 返回真;

2)假设一个类定义如下:

class Friend {
    String name;

     Friend(String n){
        this.name = n;
    }

     public boolean equals(Object o){
         return ((Friend) o).name == this.name;
     }
}

我创建了两个对象的实例:

Friend f1 = new Friend("1");
Friend f2 = new Friend("1");

f1.equals(f2)将返回真

3)最后,我定义了主方法的 MyClass:

public static void main(String[] args) {
        System.out.println(args[0] == "x");
    }

调用java MyClass xfalse 后将被打印。

1、2、3有什么区别?当两个字符串明显引用不同的对象时,为什么在情况 1 和 2 中不返回 false?

4

4 回答 4

2

根据Java 语言规范的第3.10.5节,字符串文字是“内部的”(存储并引用到一个可共享的值)以共享实例。

每个字符串文字都是对 String 类(第 4.3.3 节)实例(第 4.3.1 节、第 12.5 节)的引用(第 4.3 节)。字符串对象有一个常量值。字符串字面量——或者更一般地说,作为常量表达式值的字符串(第 15.28 节)——是“interned”的,以便使用 String.intern 方法共享唯一的实例。

这意味着两个字符串字面量引用同一个内部对象,因此在使用 比较时相等==,如示例 1 和示例 2 中所做的那样。但是,args[0]示例 3 中的字符串不是文字,但如果您比较其内部值,如下所示,表达式将为真。

System.out.println(args[0].intern() == "x"); //prints true

同样,如果您不实习示例 1 或 2 中的字符串之一,则相关表达式将为 false。

String s1 = "Monday";
String s2 = new String("Monday");
System.out.println(s1 == s2); //prints false
于 2012-10-27T09:03:18.897 回答
1

简短的回答是:字符串池。您可以在此处找到简要说明:

Java中的字符串池是什么?

还有更长的时间:

http://www.dreamincode.net/forums/topic/187631-the-string-pool/

于 2012-10-27T09:08:49.893 回答
1

尝试使用 hashCode() 方法进行调试

s1.hashCode() must be equal to s2.hashCode() 

args[0].hashCode() is not equal to "x".hashCode()
于 2012-10-27T09:12:23.747 回答
0

使用 #1 方法初始化String值会使两个变量String在内存中引用相同,因此这就是==返回 true 的原因。

但是,String最终以其他方式创建的值几乎总是会引用内存中的不同位置,因此==将返回 false。这就是为什么 equals 是检查String相等性的最佳方法。

于 2012-10-27T09:02:40.013 回答