我的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-amd64和java-17-openjdk-amd64中尝试过此操作,结果相同。
我究竟做错了什么?
myObject2是一个代理类的实例,由 Hibernate 使用Byte Buddy在运行时生成。生成的代理会拦截所有方法调用,这就是getClass()返回不同结果的原因。
作为 的替代方案getClass(),使用instanceof可能是另一种方法:
if ( !(this instanceof MyClass && o instanceof MyClass) )
{
return false;
}
Run Code Online (Sandbox Code Playgroud)
但请记住,这也instanceof有其缺点。它违反了对称原理。
您不应该首先比较这些对象,因为新对象应该与具有持久状态的 Hibernate 托管对象不同。
| 归档时间: |
|
| 查看次数: |
843 次 |
| 最近记录: |