Java @Override equals():当 this.getClass() != o.getClass() 失败但不应该失败时

Van*_*Van 3 java jpa

我的MyClass类中有这个 @Override for equals()

@Entity( name = "MyClass" )
@Table( name = "my_class" )
public class MyClass extends MySuperClass
{
  ...
  @Override
  public boolean equals( Object o )
  {
    if ( this == o )
    {
      return true;
    }
    if ( o == null || this.getClass() != o.getClass() )
    {
      return false;
    }
    if ( !super.equals( o ) )
    {
      return false;
    }
    MyClass that = ( MyClass ) o;
    return this.var1.equals( that.var1 ) && this.var2.equals( that.var2 );
  }
  ...
}
Run Code Online (Sandbox Code Playgroud)

相当标准。事实上,它遵循 Java 最佳实践。
后来我在另一个子包类(我的控制器类)中有这个:

...
package com.a.b.api.controllers;
...
import com.a.b.jpa.models.MyClass;
...
MyClass myObject1 = new MyClass( var1, var2 );
MyClass myObject2 = this.myClassRepository.getById( 1 ); // SpringBoot/Jpa/Hibernate

if ( myObject2.equals( myObject1 ) )
{
   ...do something...
}
...
this.myClassRepository.save( myObject1 );
...
Run Code Online (Sandbox Code Playgroud)

我的问题是.equals()总是在这里失败:

if ( o == null || this.getClass() != o.getClass() )
Run Code Online (Sandbox Code Playgroud)

因为java说this.getClass()o.getClass()相等。当我调试代码时(在 Intellij IDEA 2022.1 UE 中),我看到了以下内容:

this.getClass() = MyClass@13706

o.getClass = com.abjpa.models.MyClass@8f7462

但他们同一个班级!几乎每本 Java 书籍、教程、博客、Intellij IDEA 等都以这种方式演示 .equals ()我在 Ubuntu 20.04.4 LTS java-14-openjdk-amd64java-17-openjdk-amd64中尝试过此操作,结果相同。

我究竟做错了什么?

hap*_*ngs 7

myObject2是一个代理类的实例,由 Hibernate 使用Byte Buddy在运行时生成。生成的代理会拦截所有方法调用,这就是getClass()返回不同结果的原因。

作为 的替代方案getClass(),使用instanceof可能是另一种方法:

if ( !(this instanceof MyClass && o instanceof MyClass) )
{
   return false;
}
Run Code Online (Sandbox Code Playgroud)

但请记住,这也instanceof有其缺点。它违反了对称原理。

您不应该首先比较这些对象,因为新对象应该与具有持久状态的 Hibernate 托管对象不同。