public boolean equals(Object o) {
if (this == o)
return true;
if ((o == null) || (this.getClass() != o.getClass()))
return false;
else {
AlunoTE umAluno = (AlunoTE) o;
return(this.nomeEmpresa.equals(umAluno.getNomeEmpresa()) && super.equals(umAluno);
}
}
当论证是超类时,有人能解释第四行((this.getClass() != o.getClass())
)是如何工作的吗?因为这些类有不同的名称。 this.getClass
会返回与o.getClass
不同的名称,对吗?
答案 0 :(得分:0)
所以我们说有两个类。 A类和B类.A类是B类的超类。因此该方法将在B类中。" this.getClass()"引用类B的对象,而o.getClass()(超类)将引用类A.因此类B将不等于类A.意味着它将进入if语句。
答案 1 :(得分:0)
检查以下代码片段,以回答您的问题。对象O可以包含任何对象。 o.getClass()将返回对象的运行时类
public class Main {
void method(Object o) {
System.out.println(this.getClass() == o.getClass());
}
public static void main(String[] args) {
new Main().method(new Object()); // false
new Main().method(new Main()); // true
new Main().method(new String()); // false
new Main().method(new MainOne()); // false
}
}
class MainOne extends Main
{
}
答案 2 :(得分:0)
假设您的超类是SHAPE,并且您有一个类RECT,它是SHAPE的子类。 如果此变量用于RECT,而对象o也是RECT, 然后第4行将返回true,因为它们是同一个类(RECT)。 只要它们的类型在运行时相同,这两个对象就是相同的。
但是,如果Object o的类型为SQUARE,它也是SHAPE的子类, (甚至可以继承RECT)。 那么它不会等于这个指针(RECT), 因为他们的课程在运行时是不同的。
现在为什么这种类型检查在equals方法中是坏的(特别是对于 Hibernate 实体类的用例)。
如果您使用Hibernate,并且在Hibernate中缓存时,您正在检查一个新创建的对象,其类类型为RECT,而该类对象的类类型为RECT,则缓存中对象的类实际上将是一个子类 - 类型为RECT的类,因为Hibernate执行字节码操作并将对象包装在合成子类(RECT _ $$ javassist)中。
这意味着您期望相等的Hibernate缓存对象永远不会相等。
如果对象在子集合中,Hibernate将假定您要从集合中删除旧对象并在集合中创建新对象,而不是对集合中的现有对象执行(潜在)更新。 我们有遗留代码执行此操作,并且永远无法弄清楚为什么(直到现在)它一直在删除并重新插入我们的集合。
对于Hibernate实体对象,您应该使用instanceof运算符来确定两个对象是否相等 - 然后转换Object o并继续使用类SHAPE特定字段进行比较操作。
如果你的子类不应该被认为是相等的,那么你必须在每个子类中实现equals()来检查instanceof。
对于其他用例,您必须确定某人(或其他某些库)是否可能对您的类进行子类化(即使通过字节代码操作)以及是否仍应将任何子类视为相等或不。
例如,如果你在单元测试中做了任何类型的模拟,那么一个错误的equals方法可能会导致其他相等的对象由于它们的类不相等而不相等。
回到OP的代码。编码equals方法的更好方法是:
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof AlunoTE))
return false;
AlunoTE umAluno = (AlunoTE) o;
return(this.nomeEmpresa.equals(umAluno.getNomeEmpresa()) && super.equals(umAluno);
}
因为instanceof运算符总是为null返回false,所以也不需要进行空检查。