我想澄清一下我的理解是否正确:

==是一个引用比较,即两个对象都指向相同的内存位置 .equals()计算为对象中值的比较


当前回答

==和=之间的区别让我困惑了一段时间,直到我决定仔细研究一下。 他们中的许多人说比较字符串时应该使用equals而不是==。希望在这个回答中我能说出区别。

回答这个问题的最好方法就是问自己几个问题。让我们开始吧:

下面程序的输出是什么:

String mango = "mango";
String mango2 = "mango";
System.out.println(mango != mango2);
System.out.println(mango == mango2);

如果你说,

false
true

我会说你是对的,但你为什么那么说呢? 如果你说输出是,

true
false

我会说你错了,但我还是会问你,为什么你认为那是对的?

好的,让我们试着回答这个问题:

下面程序的输出是什么:

String mango = "mango";
String mango3 = new String("mango");
System.out.println(mango != mango3);
System.out.println(mango == mango3);

如果你说,

false
true

我会说你错了,但为什么现在是错的呢? 这个程序的正确输出是

true
false

请比较以上的程序并试着思考一下。

好的。现在这可能会有帮助(请阅读:打印对象的地址-不可能,但我们仍然可以使用它)。

String mango = "mango";
String mango2 = "mango";
String mango3 = new String("mango");
System.out.println(mango != mango2);
System.out.println(mango == mango2);
System.out.println(mango3 != mango2);
System.out.println(mango3 == mango2);
// mango2 = "mang";
System.out.println(mango+" "+ mango2);
System.out.println(mango != mango2);
System.out.println(mango == mango2);
 
System.out.println(System.identityHashCode(mango));
System.out.println(System.identityHashCode(mango2));
System.out.println(System.identityHashCode(mango3));

你能不能试着想想上面代码的最后三行输出: 对我来说,ideone打印了这个(你可以在这里检查代码):

false
true
true
false
mango mango
false
true
17225372
17225372
5433634

哦!现在你看到identityHashCode(mango)等于identityHashCode(芒果2)但它不等于identityHashCode(芒果3)

即使所有的字符串变量芒果,芒果2和芒果3都有相同的值,即“芒果”,identityHashCode()对所有变量仍然不相同。

现在尝试取消注释这一行// mango2 = "mang";并再次运行它,这一次你将看到所有三个identityHashCode()是不同的。 嗯,这是个有用的提示

我们知道如果hashcode(x)=N并且hashcode(y)=N => x等于y

我不确定java内部是如何工作的,但我假设这就是我说的:

mango = "mango";

Java创建了一个字符串“mango”,由变量mango指向(引用),就像这样

mango ----> "mango"

下一行我说

mango2 = "mango";

它实际上重用了相同的字符串“mango”,看起来像这样

mango ----> "mango" <---- mango2

mango和mango2都指向同一个引用 当我说

mango3 = new String("mango")

它实际上为mango创建了一个全新的引用(字符串)。就像这样,

mango -----> "mango" <------ mango2

mango3 ------> "mango"

这就是为什么当我输出mango == mango2的值时,输出的是true。当我输出mango3 == mango2的值时,它输出false(即使值是相同的)。

当你取消注释// mango2 = "mang"; 它实际上创建了一个字符串“mang”,将我们的图形变成这样:

mango ---->"mango"
mango2 ----> "mang"
mango3 -----> "mango"

这就是为什么identityHashCode对所有人来说都不一样。

希望这对你们有帮助。 实际上,我想生成一个测试用例,其中==失败而equals()通过。 如果我错了,请随意评论并让我知道。

其他回答

String池(又名实习池)和Integer池进一步模糊了区别,并允许您在某些情况下对对象使用==而不是.equals

这可以为您提供更好的性能(?),但代价是更大的复杂性。

例如:

assert "ab" == "a" + "b";

Integer i = 1;
Integer j = i;
assert i == j;

复杂性权衡:以下内容可能会让你大吃一惊:

assert new String("a") != new String("a");

Integer i = 128;
Integer j = 128;
assert i != j;

我建议你远离这样的微观优化,总是用.equals表示对象,用==表示原语:

assert (new String("a")).equals(new String("a"));

Integer i = 128;
Integer j = 128;
assert i.equals(j);

还要注意,.equals()通常包含==用于测试,因为如果您想测试两个对象是否相等,这是您希望测试的第一个东西。

而==实际上查看的是基本类型的值,对于对象,它检查引用。

==和equals()之间的主要区别是

1) ==用于比较原语。

例如:

        String string1 = "Ravi";
        String string2 = "Ravi";
        String string3 = new String("Ravi");
        String string4 = new String("Prakash");

        System.out.println(string1 == string2); // true because same reference in string pool
        System.out.println(string1 == string3); // false

2) equals()用于比较对象。 例如:

        System.out.println(string1.equals(string2)); // true equals() comparison of values in the objects
        System.out.println(string1.equals(string3)); // true
        System.out.println(string1.equals(string4)); // false

对于String类:

equals()方法比较String实例中的“值”(在堆上),而不考虑两个对象引用是否引用同一个String实例。如果任意两个String类型的对象引用引用同一个String实例,那就太好了!如果两个对象引用引用两个不同的String实例..这没什么区别。它是每个被比较的String实例中的“值”(即:字符数组的内容)。

On the other hand, the "==" operator compares the value of two object references to see whether they refer to the same String instance. If the value of both object references "refer to" the same String instance then the result of the boolean expression would be "true"..duh. If, on the other hand, the value of both object references "refer to" different String instances (even though both String instances have identical "values", that is, the contents of the character arrays of each String instance are the same) the result of the boolean expression would be "false".

就像任何解释一样,让它深入人心。

我希望这能让你清楚一点。

Equals()方法主要比较对象的原始内容。

如果我们写作

    String s1 = "Samim";
    String s2 = "Samim";
    String s3 = new String("Samim");
    String s4 = new String("Samim");

    System.out.println(s1.equals(s2));
    System.out.println(s2.equals(s3));
    System.out.println(s3.equals(s4));

输出将是

true 
true 
true

因为equals()方法比较对象的内容。 在first System.out.println()中,s1和s2的内容是相同的,这就是为什么它打印为真。 另外两个System.out.println()为真。

再一次,

    String s1 = "Samim";
    String s2 = "Samim";
    String s3 = new String("Samim");
    String s4 = new String("Samim");
    
    System.out.println(s1 == s2);
    System.out.println(s2 == s3);
    System.out.println(s3 == s4);

输出将是

true
false 
false

因为==运算符主要比较对象的引用,而不是对象的值。 在first System.out.println()中,s1和s2的引用是相同的,这就是为什么它返回true。

在第二个System.out.println()中,创建了s3对象,这就是为什么会创建另一个s3的引用,并且s2和s3的引用会有所不同,因此它返回“false”。

Third System.out.println(),遵循second System.out.println()的规则,这就是为什么它会返回"false"。