719

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

  • ==是引用比较,即两个对象都指向同一个内存位置
  • .equals()评估对象中值的比较
4

25 回答 25

702

一般来说,您的问题的答案是“是”,但是......

  • .equals(...)只会比较它所写的比较,不多也不少。
  • 如果一个类没有覆盖 equals 方法,那么它默认equals(Object o)使用最近的父类的方法,该父类已经覆盖了这个方法。
  • 如果没有父类提供覆盖,则默认为最终父类 Object 的方法,因此您只剩下该Object#equals(Object o)方法。根据 Object API,这与==; 也就是说,当且仅当两个变量都引用同一个对象时,如果它们的引用是一个且相同的,它才返回 true。因此,您将测试对象相等而不是功能相等
  • hashCode如果您覆盖,请务必记住覆盖equals,以免“违反合同”。根据 API,如果两个对象的方法表明它们是等效的,则从hashCode()两个对象的方法返回的结果必须相同。equals反过来不一定是真的。
于 2011-09-22T19:39:18.297 回答
124

关于 String 类:

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

另一方面,“==”运算符比较两个对象引用的值,看它们是否引用同一个String 实例。如果两个对象的值引用“引用”同一个 String 实例,那么布尔表达式的结果将是“true”..duh。另一方面,如果两个对象引用的值“引用”不同的 String 实例(即使两个 String 实例具有相同的“值”,即每个 String 实例的字符数组的内容相同),则布尔表达式的结果将是“假”。

与任何解释一样,让它沉入其中。

我希望这能澄清一点。

于 2012-05-29T20:24:04.583 回答
69

取决于您是在谈论“原始”还是“对象类型”,存在一些小的差异;如果您谈论的是“静态”或“非静态”成员,也可以这样说;你也可以混合以上所有...

这是一个示例(您可以运行它):

public final class MyEqualityTest
{
    public static void main( String args[] )
    {
        String s1 = new String( "Test" );
        String s2 = new String( "Test" );

        System.out.println( "\n1 - PRIMITIVES ");
        System.out.println( s1 == s2 ); // false
        System.out.println( s1.equals( s2 )); // true

        A a1 = new A();
        A a2 = new A();

        System.out.println( "\n2 - OBJECT TYPES / STATIC VARIABLE" );
        System.out.println( a1 == a2 ); // false
        System.out.println( a1.s == a2.s ); // true
        System.out.println( a1.s.equals( a2.s ) ); // true

        B b1 = new B();
        B b2 = new B();

        System.out.println( "\n3 - OBJECT TYPES / NON-STATIC VARIABLE" );
        System.out.println( b1 == b2 ); // false
        System.out.println( b1.getS() == b2.getS() ); // false
        System.out.println( b1.getS().equals( b2.getS() ) ); // true
    }
}

final class A
{
    // static
    public static String s;
    A()
    {
        this.s = new String( "aTest" );
    }
}

final class B
{
    private String s;
    B()
    {
        this.s = new String( "aTest" );
    }

    public String getS()
    {
        return s;
    }

}

您可以通过以下链接比较“==”(相等运算符)和“.equals(...)”(java.lang.Object 类中的方法)的解释:

于 2014-03-06T01:56:43.470 回答
48

== 和 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(mango2) 但它不等于 identityHashCode(mango3)

尽管所有的字符串变量——mango、mango2 和 mango3——都具有相同的值,即“mango”,identityHashCode()但对所有人来说仍然不一样。

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

我们知道 ifhashcode(x)=Nhashcode(y)=N=>x is equal to 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() 通过的测试用例。如果我错了,请随时发表评论并告诉我。

于 2016-04-05T10:55:34.267 回答
33

==运算符测试两个变量是否具有相同的引用(也就是指向内存地址的指针)。

String foo = new String("abc");
String bar = new String("abc");

if(foo==bar)
// False (The objects are not the same)

bar = foo;

if(foo==bar)
// True (Now the objects are the same)

equals()方法测试两个变量是否引用具有相同状态(值)的对象。

String foo = new String("abc");
String bar = new String("abc");

if(foo.equals(bar))
// True (The objects are identical but not same)

干杯:-)

于 2016-08-09T14:43:18.553 回答
15

您必须重写 equals 函数(以及其他函数)才能将其与自定义类一起使用。

equals 方法比较对象。

二元运算符比较==内存地址。

于 2011-09-22T19:39:26.410 回答
10

==运算符equals()也是方法

运算符通常用于原始类型比较,因此==用于内存地址比较,equals()方法用于比较对象

于 2014-01-15T03:23:55.680 回答
8

如果您不覆盖 .equals(),则 == 和 .equals() 都指向同一个对象。

覆盖 .equals() 后,它是您想要做的事情。您可以将调用对象的状态与传入的对象状态进行比较,或者您可以调用 super.equals()

于 2011-09-22T19:54:47.147 回答
8
 String w1 ="Sarat";
 String w2 ="Sarat";
 String w3 = new String("Sarat");

 System.out.println(w1.hashCode());   //3254818
 System.out.println(w2.hashCode());   //3254818
 System.out.println(w3.hashCode());   //3254818

 System.out.println(System.identityHashCode(w1)); //prints 705927765
 System.out.println(System.identityHashCode(w2)); //prints 705927765
 System.out.println(System.identityHashCode(w3)); //prints 366712642


 if(w1==w2)   //  (705927765==705927765)
 {
   System.out.println("true");
 }
 else
 {
   System.out.println("false");
 }
 //prints true

 if(w2==w3)   //  (705927765==366712642)
 {
   System.out.println("true");
 }
 else
 {
   System.out.println("false");
 }
 //prints false


 if(w2.equals(w3))   //  (Content of 705927765== Content of 366712642)
 {
   System.out.println("true");
 }
 else
 {
   System.out.println("false");
 }
 //prints true
于 2017-01-09T18:06:13.080 回答
5

请记住,这.equals(...)必须由您要比较的类来实现。否则,没有什么意义。Object 类的方法版本与比较操作执行相同的操作:Object#equals

您真正想要对对象使用比较运算符的唯一一次是您正在比较枚举。这是因为一次只有一个 Enum 值的实例。例如,给定枚举

enum FooEnum {A, B, C}

您一次永远不会有多个实例,A对于Band 也是如此C。这意味着您实际上可以编写如下方法:

public boolean compareFoos(FooEnum x, FooEnum y)
{
    return (x == y);
}

你不会有任何问题。

于 2011-09-22T21:22:41.860 回答
5

relational operator ==这是和之间区别的一般规则the method .equals()

object1 == object2比较 object1 和 object2 引用的对象是否引用Heap 中的相同内存位置

object1.equals(object2)比较object1 和 object2 的值,而不管它们在内存中的位置

可以使用 String 很好地证明这一点

方案 1

 public class Conditionals {

    public static void main(String[] args) {
       String str1 = "Hello";
       String str2 = new String("Hello");
       System.out.println("is str1 == str2 ? " + (str1 == str2 ));
       System.out.println("is str1.equals(str2) ? " + (str1.equals(str2 )));
    }

 }



The result is
      is str1 == str2 ? false
      is str1.equals(str2) ? true 

方案 2

public class Conditionals {

    public static void main(String[] args) {
       String str1 = "Hello";
       String str2 = "Hello";
       System.out.println("is str1 == str2 ? " + (str1 == str2 ));
       System.out.println("is str1.equals(str2) ? " + (str1.equals(str2 )));
    }

}

The result is 
  is str1 == str2 ? true
  is str1.equals(str2) ? true

此字符串比较可用作比较其他类型对象的基础。

例如,如果我有一个 Person 类,我需要定义比较两个人的标准。假设这个人类有身高和体重的实例变量。

因此,创建人员对象person1 and person2并使用.equals()我需要覆盖人员类的 equals 方法来比较这两个对象,以根据比较将是哪些实例变量(身高或体重)来定义。

然而,== operator will still return results based on the memory location of the two objects(person1 and person2).

为了便于概括此人对象比较,我创建了以下测试类。对这些概念进行试验将揭示大量事实

package com.tadtab.CS5044;

public class Person {

private double height;
private double weight;

public double getHeight() {
    return height;
}

public void setHeight(double height) {
    this.height = height;
}

public double getWeight() {
    return weight;
}

public void setWeight(double weight) {
    this.weight = weight;
}


@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    long temp;
    temp = Double.doubleToLongBits(height);
    result = prime * result + (int) (temp ^ (temp >>> 32));
    return result;
}

@Override
/**
 * This method uses the height as a means of comparing person objects.
 * NOTE: weight is not part of the comparison criteria
 */
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    Person other = (Person) obj;
    if (Double.doubleToLongBits(height) != Double.doubleToLongBits(other.height))
        return false;
    return true;
}

public static void main(String[] args) {
    
    Person person1 = new Person();
    person1.setHeight(5.50);
    person1.setWeight(140.00);
    
    Person person2 = new Person();
    person2.setHeight(5.70);
    person2.setWeight(160.00);
    
    Person person3 = new Person();
    person3 = person2;
    
    Person person4 = new Person();
    person4.setHeight(5.70);
    
    Person person5 = new Person();
    person5.setWeight(160.00);
    
    System.out.println("is person1 == person2 ? " + (person1 == person2)); // false;
    System.out.println("is person2 == person3 ? " + (person2 == person3)); // true 
    //this is because perosn3 and person to refer to the one person object in memory. They are aliases;
    System.out.println("is person2.equals(person3) ? " + (person2.equals(person3))); // true;
    
    System.out.println("is person2.equals(person4) ? " + (person2.equals(person4))); // true;
    
    // even if the person2 and person5 have the same weight, they are not equal.
    // it is because their height is different
    System.out.println("is person2.equals(person4) ? " + (person2.equals(person5))); // false;
}

}

此类执行的结果是:

is person1 == person2 ? false
is person2 == person3 ? true
is person2.equals(person3) ? true
is person2.equals(person4) ? true
is person2.equals(person4) ? false
于 2019-06-13T05:52:18.373 回答
4

在评估代码时,很明显 (==) 是根据内存地址进行比较,而 equals(Object o) 比较的是实例的 hashCode()。这就是为什么说如果你以后没有遇到意外,就不要破坏equals() 和hashCode() 之间的约定。

    String s1 = new String("Ali");
    String s2 = new String("Veli");
    String s3 = new String("Ali");

    System.out.println(s1.hashCode());
    System.out.println(s2.hashCode());
    System.out.println(s3.hashCode());


    System.out.println("(s1==s2):" + (s1 == s2));
    System.out.println("(s1==s3):" + (s1 == s3));


    System.out.println("s1.equals(s2):" + (s1.equals(s2)));
    System.out.println("s1.equal(s3):" + (s1.equals(s3)));


    /*Output 
    96670     
    3615852
    96670
    (s1==s2):false
    (s1==s3):false
    s1.equals(s2):false
    s1.equal(s3):true
    */
于 2017-07-22T13:31:55.230 回答
4

== 和 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
于 2017-09-23T07:08:52.630 回答
3

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

==实际上确实会查看原始类型的值,对于它检查引用的对象。

于 2015-03-24T06:15:16.113 回答
3

== 运算符总是比较引用。但万一

等于()方法

如果我们被重写 equals 方法,它取决于实现,而不是在重写方法中给出的实现的基础上比较对象。

 class A
 {
   int id;
   String str;

     public A(int id,String str)
     {
       this.id=id;
       this.str=str;
     }

    public static void main(String arg[])
    {
      A obj=new A(101,"sam");
      A obj1=new A(101,"sam");

      obj.equals(obj1)//fasle
      obj==obj1 // fasle
    }
 }

在上面的代码中,obj 和 obj1 对象都包含相同的数据,但引用不一样,所以 equals 返回 false 和 == 也。但是如果我们重写 equals 方法

 class A
 {
   int id;
   String str;

     public A(int id,String str)
     {
       this.id=id;
       this.str=str;
     }
    public boolean equals(Object obj)
    {
       A a1=(A)obj;
      return this.id==a1.id;
    }

    public static void main(String arg[])
    {
      A obj=new A(101,"sam");
      A obj1=new A(101,"sam");

      obj.equals(obj1)//true
      obj==obj1 // fasle
    }
 }

知道检查它只会在我们覆盖的相同情况下返回 true 和 false

等于方法。

它在对象的内容(id)的基础上比较对象

但是==

仍然比较对象的引用。

于 2016-02-03T17:48:05.923 回答
2

由于 Java 不支持运算符重载,因此==每个对象的行为都相同,但equals()它是方法,可以在 Java 中重写,并且可以根据业务规则更改比较对象的逻辑。

==Java中和equals之间的主要区别在于"=="用于比较原语,而equals()建议使用方法来检查对象的相等性。

字符串比较是同时使用==andequals()方法的常见场景。由于 java.lang.String 类覆盖 equals 方法,如果两个 String 对象包含相同的内容,==则返回 true,但仅当两个引用指向同一个对象时才返回 true。

这是一个在 Java 中使用==andequals()方法比较两个字符串是否相等的示例,这将消除一些疑问:

 public class TEstT{

        public static void main(String[] args) {
            
    String text1 = new String("apple");
    String text2 = new String("apple");
          
    //since two strings are different object result should be false
    boolean result = text1 == text2;
    System.out.println("Comparing two strings with == operator: " + result);
          
    //since strings contains same content , equals() should return true
    result = text1.equals(text2);
    System.out.println("Comparing two Strings with same content using equals method: " + result);
          
    text2 = text1;
    //since both text2 and text1d reference variable are pointing to same object
    //"==" should return true
    result = (text1 == text2);
    System.out.println("Comparing two reference pointing to same String with == operator: " + result);

    }
    }
于 2015-02-02T12:03:58.117 回答
2

==可以用于许多对象类型,但您可以Object.equals用于任何类型,尤其是字符串和谷歌地图标记。

于 2014-12-15T06:05:12.490 回答
2

值得补充的是,对于原始类型(即 Int、Long、Double)的包装器对象,如果两个值相等, == 将返回 true。

Long a = 10L;
Long b = 10L;

if (a == b) {
    System.out.println("Wrapped primitives behave like values");
}

相比之下,将上述两个 Long 放入两个单独的 ArrayList 中,equals 认为它​​们是相同的,但 == 则不然。

ArrayList<Long> c = new ArrayList<>();
ArrayList<Long> d = new ArrayList<>();

c.add(a);
d.add(b);
if (c == d) System.out.println("No way!");
if (c.equals(d)) System.out.println("Yes, this is true.");
于 2014-12-12T18:44:13.457 回答
2
public class StringPool {

public static void main(String[] args) {

    String s1 = "Cat";// will create reference in string pool of heap memory
    String s2 = "Cat";
    String s3 = new String("Cat");//will create a object in heap memory

    // Using == will give us true because same reference in string pool

    if (s1 == s2) {
        System.out.println("true");
    } else {
        System.out.println("false");
    }

    // Using == with reference and Object will give us False

    if (s1 == s3) {
        System.out.println("true");
    } else {
        System.out.println("false");
    }

    // Using .equals method which refers to value

    if (s1.equals(s3)) {
        System.out.println("true");
    } else {
        System.out.println("False");
    }

    }
  }

----输出----- true false true

于 2016-11-19T09:10:28.283 回答
1

String 池(又名interning )和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);
于 2016-02-14T23:35:11.050 回答
1

示例 1 -

== 和 .equals 方法都仅供参考比较。这意味着两个对象是否引用同一个对象。

对象类等于方法实现

public class HelloWorld{
     public static void main(String []args){
       Object ob1 = new Object();
       Object ob2 = ob1;
       System.out.println(ob1 == ob2); // true
       System.out.println(ob1.equals(ob2)); // true
     }    
}

在此处输入图像描述

示例 2 -

但是如果我们想使用 equals 方法比较对象的内容,那么类必须重写对象的类 equals() 方法并提供内容比较的实现。在这里,String 类重写了用于内容比较的 equals 方法。所有包装类都覆盖了用于内容比较的 equals 方法。

字符串类等于方法实现

public class HelloWorld{
     public static void main(String []args){
       String ob1 = new String("Hi");
       String ob2 = new String("Hi");
       System.out.println(ob1 == ob2); // false (Both references are referring two different objects)
       System.out.println(ob1.equals(ob2)); // true
     }
}

在此处输入图像描述

示例 3 -

对于字符串,还有一个用例。在这里,当我们将任何字符串分配给 String 引用时,就会在String 常量池中创建字符串常量。如果我们将相同的字符串分配给新的字符串引用,则不会创建新的字符串常量,而是引用现有的字符串常量。

public class HelloWorld{
     public static void main(String []args){
       String ob1 = "Hi";
       String ob2 = "Hi";
       System.out.println(ob1 == ob2); // true
       System.out.println(ob1.equals(ob2)); // true
     }
}

在此处输入图像描述

请注意,每当重写该方法时,通常都需要重写 hashCode 方法,以维护 hashCode 方法的一般约定,即相等的对象必须具有相等的哈希码。

Java API equals() 方法契约

于 2021-06-17T11:53:59.803 回答
1

简而言之,答案是“是”。

在Java中,==运算符比较两个对象,看它们是否指向同一个内存位置;而该.equals()方法实际上是比较两个对象以查看它们是否具有相同的对象值。

于 2018-10-24T15:12:52.460 回答
0

这是同一性等价性的区别。

a == b意味着 a 和 b 是相同的,也就是说,它们是内存中相同对象的符号。

a.equals( b )意味着它们是等价的,它们是在某种意义上具有相同值的对象的符号——尽管这些对象可能在内存中占据不同的位置。

请注意,对于等价,如何评估和比较对象的问题开始发挥作用——复杂的对象在实际用途中可能被认为是等价的,即使它们的某些内容不同。有了身份,就不存在这样的问题。

于 2020-06-14T15:14:32.230 回答
0

简而言之,==检查两个对象是否指向相同的内存位置,同时.equals()评估对象中值的比较。

于 2021-06-07T16:58:32.710 回答
0

基本上,==比较两个对象是否在堆上具有相同的引用,因此除非两个引用链接到同一个对象,否则这种比较将是错误的。

equals()是从Object类继承的方法。默认情况下,此方法比较两个对象是否具有相同的引用。它的意思是:

object1.equals(object2) <=> object1 == object2

然而,如果你想在同一个类的两个对象之间建立相等性,你应该重写这个方法。hashCode()如果您已覆盖,则覆盖该方法也非常重要equals()

在建立相等性时实现hashCode()是 Java 对象契约的一部分。如果您正在使用集合,并且尚未实现hashCode(),则可能会发生奇怪的坏事:

HashMap<Cat, String> cats = new HashMap<>();
Cat cat = new Cat("molly");
cats.put(cat, "This is a cool cat");
System.out.println(cats.get(new Cat("molly"));

null如果您还没有实现,将在执行前面的代码后打印hashCode()

于 2016-04-26T21:20:47.193 回答