我应该比较班级“等于”方法中的所有字段吗?

时间:2015-08-18 01:24:18

标签: java equals

我正在开发一个允许用户管理帐户的应用程序。所以,假设我有一个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保持不变,该帐户仍被视为同一帐户。
  3. 我想说的是,我基本上以这种方式实现equals,以便在应用程序的其余部分中使用更简洁,更简洁的代码。但我不确定我是否在这里违反了一些规则,或者我是否正在做一些可能导致其他开发人员头痛的事情,如果有人正在使用我的应用程序的API。

    可以只比较equals方法中的某些字段,还是应该比较所有字段?

5 个答案:

答案 0 :(得分:6)

是的,这样做绝对没问题。 决定你的类的平等意味着什么,你应该以对你的应用程序逻辑最有意义的方式使用它 - 特别是对于集合和其他类似的类来说利用平等。听起来你已经考虑过这个并决定(服务器,标识符)对是唯一区分实例的东西。

这意味着,例如,具有相同(服务器,标识符)对但具有不同accountName的两个实例是同一帐户的不同版本,并且可能需要以某种方式解决差异;这是一个非常合理的语义。

定义一个单独的boolean allFieldsEqual(Account other)方法来覆盖"扩展"可能是有意义的。定义,取决于您是否需要它(或者会发现它对测试有用)。

当然,您应该使用hashCode的任何定义覆盖equals to make it consistent

答案 1 :(得分:2)

您应该比较确定相等性所需的所有字段。如果accountIdentifierserver字段足以确定两个对象是否相等,则完全没问题。不需要包括任何其他在平等方面不重要的领域。

答案 2 :(得分:1)

答案是"这取决于数据的语义和#34;。

例如,您可以在内部存储可以从其他字段派生(计算)的字段。在这种情况下,您不需要比较计算值。

作为一个总体概括,应该包括任何不能从其他领域得出的东西。

答案 3 :(得分:1)

对于密钥,通常应使用业务密钥,此密钥可以是简单密钥,也可以是复合密钥,不需要包含实体中的所有字段。所以...取决于每种情况选择识别实体的内容。如果可能,应该是完全的最小字段数,并且唯一标识实体。

有些人更喜欢(并且是一种很好的做法)来创建一个能够识别对象的代理键,当你想要使用任何ORM来保存你的对象时,这非常有用,因为你不需要将键导出到1:M或M:N关系中的子实体。例如,如果您将样本中的ID创建为内部唯一标识符,则可将其视为代理键。

也可能需要考虑:

  • 您必须覆盖等于,您必须覆盖 hashCode ,这对于与集合,地图等类合作非常重要
  • Apache提供了一个非常好的API来帮助实现equals和hashCode。这些类是 EqualsBuilder HashCodeBuilder 。两者都允许您连接您想要在比较中使用的字段,并且还可以使用反射。

答案 4 :(得分:0)

这很好 - 可能是一件好事。如果您已确定平等为accountIdentifierserver具有独特性和独特性,那么这对您的用例完全有效。

您不希望使用超出您需要的字段,因为这会在您的代码中产生误报。这种方法非常适合您的需求。