Java getClass 和 super 类

Java getClass and super classes

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);
    }
}

谁能解释一下当参数是超级 class 时第四行 ((this.getClass() != o.getClass())) 是如何工作的?因为 classes 有不同的名字。 this.getClass 将 return 与 o.getClass 的名称不同,对吗?

所以假设有两个 class。 Class A 和 Class B。Class A 是 class B 的超 class。所以这个方法将在 class B 中。 "this.getClass()" 指的是 class B 的对象,而 o.getClass()(超级 class)将指代 class A。所以 Class B 将不等于 Class A. 意味着它将进入 if 语句。

检查以下可回答您问题的代码片段。对象 O 可以容纳任何对象。 o.getClass() 将 return 对象的 运行 时间 class

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
{
}

假设您的超级 class 是 SHAPE,并且您有一个 class RECT,它是 SHAPE 的子class。 如果 this 变量是一个 RECT 而 Object o 也是一个 RECT, 那么第 4 行将 return 为真,因为它们是相同的 class (RECT)。 只要两个对象在运行时类型相同,它们就相等。

但是,如果对象 o 是 SQUARE 类型,也属于 classes SHAPE, (甚至可以 subclass RECT)。 那么它将不等于 this 指针(RECT), 因为它们的 classes 在运行时是不同的。


现在说明为什么这种类型检查在 equals 方法中不好(特别是 Hibernate 实体 classes 的用例)。

如果您使用 Hibernate 并且您正在检查 class 类型为 RECT 的新创建对象与在 Hibernate 中缓存时 class 类型为 RECT 的对象,[=缓存中对象的 44=] 实际上是 RECT 类型的子 class,因为 Hibernate 进行字节码操作并将对象包装在合成子 class (RECT_$$javassist ).

这意味着您期望相等的 Hibernate 缓存对象永远不会相等。

如果对象在子集合中,Hibernate 将假设您想要从集合中删除旧对象并在集合中创建新对象,而不是对集合中的现有对象进行(潜在的)更新. 我们有这样做的遗留代码,永远无法弄清楚为什么(直到现在)它一直在我们的集合中进行删除和重新插入。

对于 Hibernate 实体对象,您应该使用 instanceof 运算符来确定两个对象是否相等 - 然后转换对象 o 并继续与 class SHAPE 特定字段的比较操作。

如果你的 subclasses 不应该被认为是相等的,那么你将不得不在每个 subclass 中实现 equals() 来检查 instanceof.


对于其他用例,您将必须确定是否有人(或其他库)可以子class您的Class(即使通过字节码操作)和任何子 class 是否仍应被视为相等。

例如,如果您在单元测试中进行任何类型的模拟,错误的 equals 方法可能会导致原本相等的对象不相等,因为它们 classes 不相等。


回到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 总是 returns false,所以也不需要进行 null 检查。