簡體   English   中英

我應該比較班級“等於”方法中的所有字段嗎?

[英]Should I compare all fields in my class's “equals” method?

我正在開發一個允許用戶管理帳戶的應用程序。 所以,假設我有一個Account類,代表用戶的一個帳戶:

class Account
{
    public int id;
    public String accountName;
    public String accountIdentifier;
    public String server;
    public String notes;
}

我的equals方法如下所示:

public boolean equals(Object o)
{
    if (this == o)
        return true;
    if (o == null || !(o instanceof Account))
        return false;

    Account other = (Account) o;
    if (!accountIdentifier.equals(other.accountIdentifier))
        return false;
    if (!server.equals(other.server))
        return false;
    return true;
}

如您所見,我只是比較accountIdentifierserver ,而不是其他字段。 我選擇這種方法有幾個原因。

  1. 我將帳戶保存在List 當用戶更新帳戶時,通過更改帳戶名稱(這只是用戶指定的名稱來識別帳戶)或備注,我可以執行accountList.set(accountList.indexOf(account), account); 更新列表中的帳戶。 如果equals比較所有屬性,這種方法將無法工作,我必須解決它(例如通過迭代列表並手動檢查這些屬性)。
  2. 這可能實際上更重要,但只是在思考了一段時間之后我才想到它。 AccountaccountIdentifier及其所屬的server唯一標識。 用戶可能決定重命名帳戶,或更改備注,但它仍然是同一帳戶。 但如果服務器發生變化,我想我會認為它是一個不同的帳戶。 id只是一個內部ID,因為帳戶存儲在數據庫中。 即使更改了,如果accountIdentifierserver保持不變,該帳戶仍被視為同一帳戶。

我想說的是,我基本落實equals這種方式允許在應用程序的其它部分更短,更簡潔的代碼。 但是我不確定我是否在這里違反了一些規則,或者我是否正在做一些可能導致其他開發人員頭痛的事情,如果有人正在使用我的應用程序的API。

是否可以只比較equals方法中的某些字段,還是應該比較所有字段?

是的,這樣做肯定沒問題。 可以決定什么相等對您的類有什么意義,並且您應該以對應用程序邏輯最有意義的方式使用它 - 特別是對於集合和其他使用相等的類。 聽起來你已經考慮過這個並決定(服務器,標識符)對是唯一區分實例的東西。

例如,這意味着具有相同(服務器,標識符)對但具有不同accountName的兩個實例是同一帳戶的不同版本,並且可能需要以某種方式解決差異; 這是一個非常合理的語義。

定義一個單獨的boolean allFieldsEqual(Account other)方法來覆蓋“擴展”定義可能是有意義的,這取決於您是否需要它(或者會發現它對測試有用)。

當然,您應該覆蓋hashCode ,使其與您使用的equals定義保持一致

您應該比較確定相等性所需的所有字段。 如果accountIdentifierserver字段足以確定兩個對象是否相等,那么這很好。 無需包含任何其他在平等方面無關緊要的字段。

答案是“這取決於數據的語義”。

例如,您可以在內部存儲可以從其他字段派生(計算)的字段。 在這種情況下,您無需比較計算值。

作為一個總體概括,應該包括任何不能從其他領域得出的東西。

對於密鑰,通常您應該使用業務密鑰,此密鑰可以是簡單密鑰或復合密鑰,並且不必包含實體中的所有字段。 所以...取決於每種情況選擇識別實體的內容。 如果可能,應該是完全的最小字段數,並且唯一標識實體。

有些人更喜歡(並且是一種很好的做法)來創建一個能夠識別對象的代理鍵,當你想要使用任何ORM來保存你的對象時,這非常有用,因為你不需要將鍵導出到子實體中。 1:M或M:N關系。 例如,如果將樣本中的ID創建為內部唯一標識符,則可將其視為代理鍵。

也可能要考慮:

  • 總是你覆蓋equals你必須覆蓋hashCode ,這對於像Collections,Maps等類這樣的正常工作很重要
  • Apache提供了一個非常好的API來幫助實現equals和hashCode。 這些類是EqualsBuilderHashCodeBuilder 兩者都允許您連接要在比較中使用的字段,並且還可以使用反射。

這很好 - 可能是一件好事。 如果您已將相等性標識為accountIdentifier ,並且server是獨特且唯一的,那么這對您的用例完全有效。

您不希望使用多於您需要的字段,因為這會在代碼中產生誤報。 這種方法非常適合您的需求。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM