我的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 );
}
...
}
很標準。事實上,它遵循 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 );
...
我的問題是.equals()總是在這里失敗:
if ( o == null || this.getClass() != o.getClass() )
因為 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中嘗試過,結果相同。
我究竟做錯了什么?
uj5u.com熱心網友回復:
myObject2是代理類的實體,由 Hibernate 在運行時使用Byte Buddy生成。生成的代理攔截所有方法呼叫,這就是getClass()回傳不同結果的原因。
作為 的替代方法getClass(), usinginstanceof可能是另一種方法:
if ( !(this instanceof MyClass && o instanceof MyClass) )
{
return false;
}
但是請記住,這instanceof有其缺點。它違反了對稱原則。
首先,您不應該比較這些物件,因為新物件應該不同于具有持久狀態的 Hibernate 托管物件。
uj5u.com熱心網友回復:
我將這個標準equals和hashcode實作用于 JPA 物體(如此處所述):
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof MyClass)) {
return false;
}
MyClass other = (MyClass) o;
return id != null && id.equals(other.getId());
}
@Override
public int hashCode() {
return getClass().hashCode();
}
uj5u.com熱心網友回復:
您沒有使用最佳實踐。將您的 equals 更改為如下所示(首先進行空檢查,然后進行相同檢查,然后進行類檢查):
public boolean equals(Object obj) {
if (obj == null) { return false; }
if (obj == this) { return true; }
if (obj.getClass() != getClass()) {
return false;
}
... do the actual comparison here
}
注意:上面的代碼是Apache EqualsBuilder的釋義
uj5u.com熱心網友回復:
快樂的歌曲在他的回復中正確地陳述:
myObject2 是代理類的一個實體,由 Hibernate 在運行時使用 Byte Buddy 生成。生成的代理攔截所有方法呼叫,這就是 getClass() 回傳不同結果的原因。
我真的不想使用instanceof,因為這被認為是不好的做法,所以我開始四處尋找并偶然發現一篇有類似問題的帖子。他們的解決方案是將final關鍵字添加到他們的類宣告中。我認為這微不足道,但試了一下——它奏效了!添加final關鍵字導致
if ( o == null || this.getClass() != o.getClass() )
和
if ( o == null || !this.getClass().equals( o.getClass() ) )
正常作業。我的課程代碼現在是:
@Entity( name = "MyClass" )
@Table( name = "my_class" )
final public class MyClass extends MySuperClass
{
...
@Override
public boolean equals( Object o )
{
if ( this == o )
{
return true;
}
if ( o == null || !this.getClass().equals( 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 );
}
...
}
謝謝大家的幫助!非常感謝快樂的歌曲為我指明了正確的方向!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/462570.html
