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.
自动生成的equals方法如上所示。
My questions are:
我的问题是:
- Why do I need to manually replace:
为什么我需要手动更换:
o == null || getClass() != o.getClass()
o == null || getClass()!= o.getClass()
into
!(o instanceof Example)
!(o instanceof Example)
- 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?
如果此类的对象将放在java.util.Set中会发生什么?在违反合同规则的哪个部分?
2 个解决方案
#1
2
The main difference is that instanceof will return true if o has inheritance of the object whereas getClass comparation will check if both objects are strictly the same class.
主要区别在于,如果o具有对象的继承,则instanceof将返回true,而getClass比较将检查两个对象是否严格相同。
#2
1
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.
特别是当您计划创建类的子类并重写equals时,以及当您没有计划这将无问题时(在大多数情况下)。所以你不需要手动更换任何东西。
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.
原因如下。 equals方法需要在对象上引入等价关系,特别是它应该是对称的:如果a.equals(b)它也必须是b.equals(a)的情况,反之亦然。许多使用equals方法的类(如地图和集合)都会采用此行为。
Now, suppose you replace o == null || getClass() != o.getClass()
with !(o instanceof Example)
, and create a subclass a follows:
现在,假设你替换o == null || getClass()!= o.getClass()with!(o instanceof Example),并创建一个子类a:
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.
您现在有一个非对称的equals方法,这可能会在使用集合时导致问题。
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()
但请注意,在某些情况下,您实际上想要使用instanceof。例如,接口Set的equals方法的Javadoc指定当两个集合包含相同的元素时,它们被认为是相等的。因此,如果HashSet包含相同的元素,则它们等于TreeSet,即使这两个集合属于不同的类。在这种情况下,当然,使用getClass()== o.getClass()是不合适的。
#1
2
The main difference is that instanceof will return true if o has inheritance of the object whereas getClass comparation will check if both objects are strictly the same class.
主要区别在于,如果o具有对象的继承,则instanceof将返回true,而getClass比较将检查两个对象是否严格相同。
#2
1
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.
特别是当您计划创建类的子类并重写equals时,以及当您没有计划这将无问题时(在大多数情况下)。所以你不需要手动更换任何东西。
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.
原因如下。 equals方法需要在对象上引入等价关系,特别是它应该是对称的:如果a.equals(b)它也必须是b.equals(a)的情况,反之亦然。许多使用equals方法的类(如地图和集合)都会采用此行为。
Now, suppose you replace o == null || getClass() != o.getClass()
with !(o instanceof Example)
, and create a subclass a follows:
现在,假设你替换o == null || getClass()!= o.getClass()with!(o instanceof Example),并创建一个子类a:
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.
您现在有一个非对称的equals方法,这可能会在使用集合时导致问题。
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()
但请注意,在某些情况下,您实际上想要使用instanceof。例如,接口Set的equals方法的Javadoc指定当两个集合包含相同的元素时,它们被认为是相等的。因此,如果HashSet包含相同的元素,则它们等于TreeSet,即使这两个集合属于不同的类。在这种情况下,当然,使用getClass()== o.getClass()是不合适的。