简体   繁体   中英

Class compare vs instanceof in equals method java

Like in a title: My Entity looks like this:

@Entity
public class Example {

    @Id
    private Integer id;
    private String name;

    // fields, getters & setters ommited 

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }

        Example example = (Example) o;

        return id != null ? id.equals(examle.id) : examle.id == null;
    }

    @Override
    public int hashCode() {
        return id != null ? id.hashCode() : 0;
    }
}

Auto generated equals method looks like above.

My questions are:

  1. Why do I need to manually replace:

o == null || getClass() != o.getClass()

into

!(o instanceof Example)

  1. What will happen if the objects of this class will be placed in java.util.Set? In what part the rule of contract will be violated?

主要区别在于,如果o具有对象的继承,则instanceof将返回true,而getClass比较将检查两个对象是否严格属于同一类。

As a rule of thumb, in your own classes it is almost always better to use

if (o == null || getClass() != o.getClass()) return false;

This is in particular the case when you plan to create subclasses of your class and override equals , but also when you're not planning that this will work without problem (in most cases). So you don't need to manually replace anything.

The reason is the following. The equals method is required to induce an equivalence relation on objects, in particular it is supposed to be symmetric: if a.equals(b) it must also be the case that b.equals(a) and vice versa. Many classes which use the equals method, such as maps and sets, assume this behavior.

Now, suppose you replace o == null || getClass() != o.getClass() o == null || getClass() != o.getClass() with !(o instanceof Example) , and create a subclass a follows:

class Subclass extends Example {
    String address;
    // fields, getters and setters
    public boolean equals(Object o) {
        if (!o instanceof Subclass) {
            return false;
        } else {
            return super.equals(o) && Objects.equals(((Subclass)o).address, address);
        }
    }
}

Now consider the following code:

Example a = new Example(); 
a.setId(1);
a.setName("A");
Subclass b = new Subclass();
b.setId(1);
b.setName("A");
b.setAddress("Street 1");
System.out.println(a.equals(b)); // Prints true
System.out.println(b.equals(a)); // Prints false

You have now an equals method which is not symmetric, and this may lead to problems when using collections.

Note, however, that in some cases, you actually want to use instanceof . For example, the Javadoc for the equals method of the interface Set specifies that two sets are considered equal when they contain the same elements. So, a HashSet is equal to a TreeSet if they contain the same elements, even though the two sets belong to different classes. In such cases, of course, it is not appropriate to use getClass() == o.getClass()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM