我正在开发一个允许用户管理帐户的应用程序。所以,假设我有一个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;
}
如您所见,我只是比较accountIdentifier
和server
,而不是其他字段。我选择这种方法有几个原因。
List
。当用户更新帐户时,通过更改帐户名称(只是用户指定的名称来识别帐户)或备注,我可以accountList.set(accountList.indexOf(account), account);
更新列表中的帐户。如果equals
比较了所有属性,这种方法就行不通了,我必须解决它(例如通过迭代列表并手动检查这些属性)。Account
由accountIdentifier
及其所属的server
唯一标识。用户可能决定重命名帐户,或更改备注,但它仍然是同一帐户。但如果服务器发生变化,我想我会认为它是一个不同的帐户。 id
只是一个内部ID,因为帐户存储在数据库中。即使改变了,如果accountIdentifier
和server
保持不变,该帐户仍被视为同一帐户。我想说的是,我基本上以这种方式实现equals
,以便在应用程序的其余部分中使用更简洁,更简洁的代码。但我不确定我是否在这里违反了一些规则,或者我是否正在做一些可能导致其他开发人员头痛的事情,如果有人正在使用我的应用程序的API。
可以只比较equals
方法中的某些字段,还是应该比较所有字段?
答案 0 :(得分:6)
是的,这样做绝对没问题。 你决定你的类的平等意味着什么,你应该以对你的应用程序逻辑最有意义的方式使用它 - 特别是对于集合和其他类似的类来说利用平等。听起来你已经考虑过这个并决定(服务器,标识符)对是唯一区分实例的东西。
这意味着,例如,具有相同(服务器,标识符)对但具有不同accountName的两个实例是同一帐户的不同版本,并且可能需要以某种方式解决差异;这是一个非常合理的语义。
定义一个单独的boolean allFieldsEqual(Account other)
方法来覆盖"扩展"可能是有意义的。定义,取决于您是否需要它(或者会发现它对测试有用)。
当然,您应该使用hashCode
的任何定义覆盖equals
to make it consistent。
答案 1 :(得分:2)
您应该比较确定相等性所需的所有字段。如果accountIdentifier
和server
字段足以确定两个对象是否相等,则完全没问题。不需要包括任何其他在平等方面不重要的领域。
答案 2 :(得分:1)
答案是"这取决于数据的语义和#34;。
例如,您可以在内部存储可以从其他字段派生(计算)的字段。在这种情况下,您不需要比较计算值。
作为一个总体概括,应该包括任何不能从其他领域得出的东西。
答案 3 :(得分:1)
对于密钥,通常应使用业务密钥,此密钥可以是简单密钥,也可以是复合密钥,不需要包含实体中的所有字段。所以...取决于每种情况选择识别实体的内容。如果可能,应该是完全的最小字段数,并且唯一标识实体。
有些人更喜欢(并且是一种很好的做法)来创建一个能够识别对象的代理键,当你想要使用任何ORM来保存你的对象时,这非常有用,因为你不需要将键导出到1:M或M:N关系中的子实体。例如,如果您将样本中的ID创建为内部唯一标识符,则可将其视为代理键。
也可能需要考虑:
答案 4 :(得分:0)
这很好 - 可能是一件好事。如果您已确定平等为accountIdentifier
且server
具有独特性和独特性,那么这对您的用例完全有效。
您不希望使用超出您需要的字段,因为这会在您的代码中产生误报。这种方法非常适合您的需求。