关于java:当我们有==运算符时为什么是equals()方法?

why equals() method when we have == operator?

本问题已经有最佳答案,请猛点这里访问。

当我看到equals()方法的实现时,它只做了与==方法相同的事情。所以我的问题是,当我们有一个执行相同工作的==操作符时,需要将它作为单独的方法来做什么?


您不能重载==运算符,但如果您希望它的行为与==运算符不同,即不比较引用,而是实际比较对象(例如使用全部或部分字段),则可以重写equals(Object)

另外,如果您确实覆盖了equals(Object),那么也可以查看hashCode()。这两种方法需要兼容(即根据equals(Object)相等的两个对象需要具有相同的hashCode()),否则会发生各种奇怪的错误(例如,将对象添加到集合或地图时)。


==比较对象引用,询问两个引用是否相同。

equals()比较对象内容,询问对象是否代表相同的概念。


对于原语,==运算符检查两个值是否相同。如果它不是基元,则检查它是否是指向同一对象实例的两个指针(或引用)。

equals()方法使用==执行自定义检查,该检查位于Object检查引用中。但在其他类中,有时会重写equals()(I don't know if this is a correct past participle)equals()必须检查内容。

例如:

1
2
3
4
5
6
7
int i0 = 34;
int i1 = 34;
int i2 = 35;
// results
i0 == i1: true
i1 == i0: true
i2 == i0: false

但是如果我们有非原始的

1
2
3
4
5
6
7
8
9
10
String str0 = new String("Hello man!");
String str1 = new String("Hello man!");
String str2 = new String("!nam olleH");
String str2copy = str2;
// Results
str0 == str1: false // Pointer to two different object, so == will give false
str1 == str2: false // Idem
str2 == str2copy: true // So this are two pointers to the same object
str0.equals(str1): true // This are not the same objects, but they are equal
str1 == str1: true // Again: two times a pointer to the same  object

那么,为什么str0.equals(str1)返回true?因为String类具有对equals()的重写。在这个方法中,它不通过执行return this == obj;来检查它们是否相等,但是在这个方法中,有一个完整的检查。我不知道他们使用哪种方法来比较这两个字符串,但有两种可能的方法:

  • 从两个字符串生成一个哈希代码,并检查它们是否相等(int == int)
  • 逐个字符检查是否相同。

所以我希望现在一切都清楚了。


==运算符用于比较引用。equals()方法是在对象定义上定义的。

1
2
3
4
5
6
7
8
Dog d =new Dog();
Collar c =new Collar("Red");
 d.setCollar(c);
Dog d2=new Dog();
 Collar c2=new Collar("Red");
d2.setCollar(c2);

 d2.getCollar() ==d.getCollar()

会返回假,表示这两只狗有两个不同的项圈对象(项目)。它们不共享同一个项圈。

1
d2.getCollar().equals(d.getCollar())

如果领口定义为[领口颜色相同,则返回"真"]这两只狗的领子是一样的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
   class Collar{
    String color="";
    public Collar(String p0){
    this.color=p0;
    }
    boolean equals(Object c){
      Collar other=(Collar)c;
      return  this.color.equals(other.getColor());
    }

    public String getColor(){
      return this.color;
    }
    }

两者之间有一个非常重要的区别。

"=="比较对象实例。默认的equals()实现也会这样做。请运行并分析以下代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class Person{
   String name;

   public Person(String name){
       this.name = name;
   }

//overriding equals
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( name == null ) {
            if( other.name != null )
            return false;
    } else if( !name.equals( other.name ) )
        return false;
    return true;
    }
     }

    ...
    ...
    Person john1 = new Person("John");
    Person john2 = new Person("John");
    System.out.println("john1 == john2:" + (john1 == john2));
    System.out.println("john1.equals(john2):" + john1.equals(john2));

如您所见,"=="将返回false(对象是两个不同的Person实例),而equals将返回true(因为我们定义了两个具有相同名称的人是相等的)


这样做是为了使这成为可能:

1
2
3
4
5
String s1 = new String("foo");
String s2 = new String("foo");

System.out.println(s1 == s2); // false?! Different references!
System.out.println(s1.equals(s2)); // true

如果您检查EDOCX1的源(9),您将看到它已经适当地覆盖了Object#equals(),以比较彼此的内部字符数组(实际值)。许多其他类也重写了这个方法。


在Java中,如果操作数是原始数据类型,则操作符(==)操作两个变量的数据。但是如果操作数是对象,Java使用引用比较它们,因为它没有办法去比较对象的哪个字段或字段。

因此,只有一种方法可以根据用户定义的字段进行比较,并且通过重写均衡器()方法来定义对象中的对象,因为在Java中不支持操作符重写的情况下,在Java中不能重写等号运算符(==)。

例如,如果要根据名称比较Employee,则需要通过重写Employee类中的Equals方法来定义其逻辑,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class Employee {
    private Integer id;
    private String name;

    @Override
    public boolean equals(Object obj) {
        Employee other = (Employee) obj;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }

    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }


}

"string"="string"将返回false"string".equals("string")将返回true

对于o1==o2,比较对象1与o2是同一个对象(通过引用)

对于o1.equals(o2),根据对象的不同,equals方法被重写,而不是用"returno1==o2"之类的方法实现。

例如,创建2个集合实例这两个集合对象是两个不同的对象,您可以在其中任何一个对象中添加不同的元素。set1==set2总是返回false但如果set2包含与set1完全相同的元素,则set1.equals(set2)最终将返回true…因为equals方法在set类中被重写…

集合的等于实现为:

1
2
3
4
5
6
7
8
9
10
11
      public boolean equals(Object o) {
        if (o == this)
           return true;

        if (!(o instanceof Set))
             return false;
        Set s = (Set) o;
        if (s.size() != c.size())
             return false;
        return containsAll(s); // Invokes safe containsAll() above
    }