@EqualsAndHashCode
簡化相等性:從物件的欄位產生 hashCode
和 equals
實作。
概觀
任何類別定義都可以使用 @EqualsAndHashCode
註解,讓 lombok 產生 equals(Object other)
和 hashCode()
方法的實作。預設情況下,它會使用所有非靜態、非瞬態的欄位,但您可以修改要使用的欄位(甚至可以指定要使用各種方法的輸出),方法是使用 @EqualsAndHashCode.Include
或 @EqualsAndHashCode.Exclude
標記類型成員。或者,您可以精確地指定您希望使用的欄位或方法,方法是使用 @EqualsAndHashCode.Include
標記它們,並使用 @EqualsAndHashCode(onlyExplicitlyIncluded = true)
。
如果將 @EqualsAndHashCode
應用於擴展另一個類別的類別,此功能會變得有點棘手。通常,為此類類別自動產生 equals
和 hashCode
方法不是一個好主意,因為父類別也定義了欄位,這些欄位也需要 equals/hashCode 程式碼,但此程式碼不會被產生。透過將 callSuper
設定為 true,您可以將父類別的 equals
和 hashCode
方法包含在產生的方法中。對於 hashCode
,super.hashCode()
的結果會包含在雜湊演算法中,而對於 equals
,如果父類別實作認為它與傳入的物件不相等,則產生的方法將傳回 false。請注意,並非所有 equals
實作都能正確處理這種情況。但是,lombok 產生的 equals
實作確實能正確處理這種情況,因此如果您的父類別也具有 lombok 產生的 equals
方法,您可以安全地呼叫父類別的 equals 方法。如果您有一個明確的父類別,您必須為 callSuper
提供一些值,以確認您已考慮過它;否則會導致警告。
當您沒有擴展任何東西(您擴展 java.lang.Object
)時,將 callSuper
設定為 true 是編譯時期錯誤,因為它會將產生的 equals()
和 hashCode()
實作變成與僅從 java.lang.Object
繼承這些方法相同的行為:只有相同的物件才會彼此相等,並且具有相同的 hashCode。當您擴展另一個類別時,不將 callSuper
設定為 true 會產生警告,因為除非父類別沒有(相等性重要的)欄位,否則 lombok 無法為您產生考慮到父類別宣告的欄位的實作。您需要編寫自己的實作,或依賴 callSuper
鏈接機制。您也可以使用 lombok.equalsAndHashCode.callSuper
設定鍵。
請注意,lombok 僅將 .equals()
實作委派給所有物件,除了 基本類型和陣列。某些知名的類型可能具有令人驚訝的 equals 實作。例如,java.math.BigDecimal
會考慮比例,即根據 BigDecimal
自己的 equals
實作,1E2
不等於 100
。
注意: 透過編寫一個傳回對應值的方法,並使用 @EqualsAndHashCode.Include(replaces = "fieldName")
註解它,可以輕鬆覆寫任何欄位的 equals 行為。例如,為了處理 BigDecimal
相等性問題,您可以編寫 @EqualsAndHashCode.Include BigDecimal fieldName() { return fieldName.stripTrailingZeros(); }
。
Lombok 0.10 新功能: 除非您的類別是 final
且擴展 java.lang.Object
,否則 lombok 會產生一個 canEqual
方法,這表示 JPA 代理仍然可以等於它們的基底類別,但新增新狀態的子類別不會破壞 equals 契約。本文解釋了為什麼需要此方法的複雜原因:How to Write an Equality Method in Java。如果階層中的所有類別都是 scala case class 和具有 lombok 產生的 equals 方法的類別的混合,則所有相等性都將「正常運作」。如果您需要編寫自己的 equals 方法,則在變更 equals
和 hashCode
時,應始終覆寫 canEqual
。
Lombok 1.14.0 新功能: 若要將註解放在 equals
(以及相關的 canEqual
)方法的 other
參數上,您可以使用 onParam=@__({@AnnotationsHere})
。但請小心!這是一個實驗性功能。如需更多詳細資訊,請參閱關於 onX 功能的文件。
Lombok 1.18.16 新功能: 可以透過將 cacheStrategy
設定為 CacheStrategy.NEVER
以外的值來快取產生的 hashCode()
結果。如果 註解類別的物件可以以任何可能導致 hashCode()
結果變更的方式修改,請勿 使用此功能。
使用 Lombok
import lombok.EqualsAndHashCode;
|
原生 Java
import java.util.Arrays;
|
支援的組態鍵
-
lombok.equalsAndHashCode.doNotUseGetters
= [true
|false
] (預設值:false) - 如果設定為
true
,lombok 將直接存取欄位,而不是在使用 getters(如果可用)產生equals
和hashCode
方法時。註解參數 'doNotUseGetters
',如果明確指定,將優先於此設定。 -
lombok.equalsAndHashCode.callSuper
= [call
|skip
|warn
] (預設值:warn) - 如果設定為
call
,如果您的類別擴展了某些東西,lombok 將產生對父類別hashCode
和equals
實作的呼叫。如果設定為skip
,則不會產生此類呼叫。預設行為類似於skip
,但會額外發出警告。 -
lombok.equalsAndHashCode.flagUsage
= [warning
|error
] (預設值:未設定) - 如果已設定,Lombok 將任何
@EqualsAndHashCode
的使用標記為警告或錯誤。
小字體聲明
陣列會進行「深度」比較/雜湊編碼,這表示包含自身的陣列將導致 StackOverflowError
。但是,此行為與例如 ArrayList
沒有不同。
您可以安全地假設使用的 hashCode 實作在 lombok 版本之間不會變更,但是此保證並非一成不變;如果使用替代雜湊演算法可以獲得顯著的效能提升,則將在未來版本中替換它。
為了相等性的目的,浮點數和倍精度的 2 個 NaN
(非數字)值被視為相等,即使 'NaN == NaN' 會傳回 false。這類似於 java.lang.Double
的 equals 方法,實際上是為了確保將物件與自身的精確副本進行比較時,會針對相等性傳回 true
。
如果存在任何名為 hashCode
或 equals
的方法,無論傳回類型為何,都不會產生任何方法,而是發出警告。這 2 個方法需要彼此同步,除非 lombok 產生所有方法,否則 lombok 無法保證這一點,因此如果其中一個或兩個方法已存在,您總是會收到警告。您可以使用 @lombok.experimental.Tolerate
標記任何方法,以將它們從 lombok 中隱藏。
嘗試排除不存在或無論如何都會被排除(因為它們是靜態或瞬態)的欄位,會在命名的欄位上產生警告。
如果一個方法被標記為包含,並且它與欄位具有相同的名稱,它將取代該欄位(該方法被包含,該欄位被排除)。
在 lombok 1.16.22 之前,可以使用 @EqualsAndHashCode
註解的 of
和 exclude
參數完成包含/排除。此舊式包含機制仍然受支援,但未來將被棄用。
預設情況下,任何以 $ 符號開頭的變數都會自動排除。您只能透過使用 @EqualsAndHashCode.Include
標記它們來包含它們。
如果包含的欄位存在 getter,則會呼叫它,而不是使用直接欄位參考。此行為可以被抑制
@EqualsAndHashCode(doNotUseGetters = true)
如果您已透過 lombok.config
鍵 lombok.addNullAnnotations
設定了空值註解風格,則產生的 equals
方法以及任何 canEqual
方法的參數都會使用可為 null 的註解進行註解。如果您將 @NonNullByDefault
樣式註解與嚴格的空值檢查結合使用,則這是必要的。