此问题特别与覆盖具有大量字段的对象的equals()方法有关。首先,让我说这个大型对象不能在不违反OO原则的情况下分解为多个组件,因此告诉我“没有类应该有超过x个字段”将无济于事。
接下来,当我忘记检查其中一个字段是否相等时,问题就出现了。因此,我的equals方法不正确。然后我想用反射:
--code removed because it was too distracting--
这篇文章的目的不一定是重构代码(这甚至不是我正在使用的代码),而是要获得关于这是否是一个好主意的输入。
优点:
缺点:
有什么想法吗?
答案 0 :(得分:13)
如果您出于性能原因确实想要列入白名单,请考虑使用注释来指示要比较的字段。此外,如果您的字段没有equals()
的良好实现,则此实现将不起作用。
P.S。如果你走equals()
这条路线,不要忘记为hashCode()
做类似的事情。
P.P.S。我相信您已经考虑过HashCodeBuilder和EqualsBuilder。
答案 1 :(得分:9)
使用Eclipse,FFS!
删除hashCode并使用等于你的方法。
右键单击该文件。
选择来源 - >生成哈希码并等于...
完成!不再担心反思。
对添加的每个字段重复一遍,只需使用大纲视图删除两个方法,然后让Eclipse自动生成它们。
答案 2 :(得分:5)
如果你采用反思方法,EqualsBuilder仍然是你的朋友:
public boolean equals(Object obj) {
return EqualsBuilder.reflectionEquals(this, obj);
}
答案 3 :(得分:2)
如果你担心,这是一个想法:
1 /在添加/删除字段时,忘记更新大系列的if语句以检查相等性。
2 /在equals()方法中执行此操作的性能。
尝试以下方法:
a /恢复使用equals()方法中的if语句的长序列。
b /具有单个函数,其中包含字段列表(在字符串数组中),并且将根据实际情况检查该列表(即反射字段)。如果它们不匹配,它将抛出异常。
c /在此对象的构造函数中,对此函数进行同步的run-once调用(类似于单例模式)。换句话说,如果这是该类构造的第一个对象,则调用上面(b)中描述的检查函数。
如果您没有更新if语句以匹配反射字段,则在运行程序时,例外会立即显现;然后你修复if语句并从上面的(b)更新字段列表。
对象的后续构造不会进行此检查,并且您的equals()方法将以最大可能的速度运行。
尽可能地尝试,我无法找到这种方法的任何实际问题(StackOverflow上可能存在更多的思想) - 对于一次运行行为,每个对象构造都有一个额外的条件检查但是看起来相当公平次要的。
如果你努力尝试,你仍然可以使用你的字段列表和反射字段来获取你的if语句,但例外情况将确保你的字段列表与反射字段匹配,你只需确保更新if-声明和字段列表同时显示。
答案 4 :(得分:1)
您可以随时在equals方法中注释您/不想要的字段,这应该是一个简单而简单的更改。
性能显然与实际比较对象的频率有关,但很多框架都使用哈希映射,所以你的等号可能比你想象的更多。
另外,谈到哈希映射,hashCode方法也存在同样的问题。
最后,你真的需要比较所有字段是否相等?
答案 5 :(得分:1)
您的代码中有一些错误。
this
和obj
是同一个类。实际上,它明确允许obj
成为任何其他类。您可以从if ( ! obj instanceof myClass ) return false;
开始,但这仍然不正确,因为obj
可能是this
的子类,其他字段可能很重要。null
obj
的{{1}}值
if ( obj == null ) return false;
和空字符串视为相等。而是特别对待null
。这里最简单的方法是首先比较null
。如果它们都相等或者两者都碰巧指向同一个对象,那么这很快。 (注意:这也是一个优化,您需要这是一个缓慢的例程。)如果失败,您可以使用快速Field.get(obj) == Field.get(this)
来处理只有if ( Field.get(obj) == null || Field.get(this) == null ) return false;
的情况。最后,您可以使用通常的null
。equals()
我同意汉克的观点,foundMismatch
和[HashCodeBuilder][1]
是更好的方法。它很容易维护,而不是很多样板代码,你可以避免所有这些问题。
答案 6 :(得分:1)
您可以使用注释从支票中排除字段
e.g。
@IgnoreEquals
String fieldThatShouldNotBeCompared;
当然,您可以检查通用等于方法中是否存在注释。
答案 7 :(得分:0)
如果您可以访问这些字段的名称,为什么不将它们作为标准,您不想包含的字段始终以“local”或“nochk”或类似的字体开头。
然后你将所有以此开头的字段列入黑名单(代码不那么难看)。
我不怀疑它有点慢。您需要决定是否要根据执行速度交换易用性。
答案 8 :(得分:-1)
看看org.apache.commons.EqualsBuilder: