Java:clean方法在调用hashCode()和equals()时自动抛出UnsupportedOperationException?
我们有一个OO代码库,在很多情况下, hashcode()
和equals()
根本不起作用,主要原因如下:
除非您愿意放弃面向对象抽象的好处,否则无法扩展可实例化的类并在保留等价契约的同时添加一个值组件。
这是来自Joshua Bloch的“Effective Java”的一句话,这里有一篇关于该主题的更多内容:
http://www.artima.com/lejava/articles/equality.html
我们完全可以这么做,这不是这个问题的关键。
问题是:看到在某些情况下你不能满足equals()
约定是一个事实,那么自动使hashcode()
和equals()
抛出UnsupportedOperationException的干净方法是什么?
注释是否有效? 我正在考虑类似@NotNull
事情:每个@NotNull
合同违规都会自动抛出一个异常,除了使用@NotNull
注释参数/返回值外,您没有别的办法可做。
这很方便,因为它是8个字符(“@NotNull”),而不是不断重复相同的验证/抛出异常代码。
在我担心的情况下,在每一个hashCode()/equals()
没有意义的实现中,我们总是重复同样的事情:
@Override
public int hashCode() {
throw new UnsupportedOperationException( "contract violation: calling hashCode() on such an object makes no sense" );
}
@Override
public boolean equals( Object o ) {
throw new UnsupportedOperationException( "contract violation: calling equals() on such an object makes no sense" );
}
然而,这很容易出错:我们可能会错误地忘记剪切/粘贴它,并且可能导致用户滥用这些对象(比如通过尝试将它们放入默认Java集合中)。
或者如果注释不能产生这种行为,AOP会起作用吗?
有趣的是,真正的问题是,在Java层次结构的顶部存在hashCode()
和equals()
,这在很多情况下是毫无意义的。 但是,我们如何干净地处理这个问题呢?
你为什么不让IDE(Eclipse / NetBeans / IntelliJ)为你生成hashCode()
和equals()
方法。 他们在这方面做得很好。
AOP当然会起作用,但这是相当复杂的。 这意味着你将无法使用这些对象几乎没有收集或实用程序。
另一个合理的解决方案是只删除那些他们不工作的方法的实现,thsus只在Object
保留实现。
我同意你对hashCode
的这个问题的评估,并且equals
于首先在Object中定义的问题。 我一直认为平等应该像排序一样处理 - 用一个接口说“我可以与X的实例进行比较”,另一个说法是“我可以比较两个X的实例”。
另一方面,这实际上是否为您造成了任何错误? 有人一直试图使用equals
和hashCode
,他们不应该? 因为即使您可以使代码库中的每个类都引发异常(如果这些方法被不适当地调用),那么您使用的其他类(不论是来自JDK还是第三方库)都不会发生这种情况。
我相信你可以用某种形式或其他形式的AOP来做到这一点,无论这是正常的注释处理还是其他的东西 - 但是你有证据表明奖励值得付出努力吗?
另一种看待它的方式是:只有在你扩展另一个已经覆盖hashCode
和equals
,对吧? 否则,您可以使用Object的hashCode / equals方法的“equals = identity”特性,这仍然有用。 你有很多属于这个类别的课程吗? 你能不能直接写一个单元测试来通过反射来找到所有这样的类型,并且在调用hashCode
/ equals
时检查这些类型是否抛出异常? (如果它们有一个无参数的构造函数,或者有一个已经检查过的类型的手动列表,那么它可以是自动的 - 如果有一个新类型不在“已知好”列表中,那么单元测试可能会失败。)
我不明白你为什么认为“在某些情况下你不能满足平等()合同”? 平等的含义是由班级定义的。 因此,使用Object的平等是完全有效的。 如果你不覆盖平等,那么你将每个实例定义为唯一的。
似乎有一种误解认为,平等是其中一种总是需要压倒一切的方法,而且它必须检查它的所有领域。 我会争辩相反的 - 不要重写平等,除非你的平等定义不同。
我也不同意artima的文章,特别是“陷阱#3:以可变域定义平等”。 对于一个类来说,基于可变字段来定义它的等式是完全有效的。 用户在使用集合时注意到这一点。 如果一个可变对象在其可变状态下定义它的相等性,那么在一个变化后不要指望两个实例是等于的。
我认为抛出UnsupportedOperation违反了平等的冲刺。 对象的等于状态:
Object类的equals方法实现对象上最可能的等价关系; 也就是说,对于任何非空引用值x和y,当且仅当x和y引用同一对象(x == y的值为true)时,此方法返回true。
所以,我应该能够调用equals并根据Object的等于定义或重写的equals定义获取真或假的值。
链接地址: http://www.djcxy.com/p/76209.html下一篇: Comparable and Comparator contract with regards to null