Syn*_*r0r 14 java design-by-contract equals
我们有一个OO代码库,在很多情况下hashcode()并且equals()根本不起作用,主要是由于以下原因:
除非您愿意放弃面向对象抽象的好处,否则无法扩展可实例化的类并在保留equals合同的同时添加值组件.
这是Joshua Bloch撰写的"Effective Java"的引用,在这篇伟大的Artima文章中有关于该主题的更多内容:
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" );
}
Run Code Online (Sandbox Code Playgroud)
然而,这很容易出错:我们可能会忘记剪切/粘贴此内容,这可能会导致用户滥用此类对象(例如,尝试将它们放入默认的Java集合中).
或者,如果无法创建注释来创建此行为,AOP是否有效?
有趣的是,真正的问题是Java层次结构的存在hashCode()和equals()顶层,在某些情况下根本没有意义.但那我们如何干净地处理这个问题呢?
Jon*_*eet 10
我同意你对这个问题的评估,hashCode并equals首先在Object中定义.我一直认为应该按照与排序相同的方式处理相等 - 使用一个界面说"我可以与一个X实例进行比较",另一个说"我可以比较两个X实例".
另一方面,这实际上是否为您造成了任何错误?有人一直在尝试用equals和hashCode他们不应该?因为即使你可以在每一个类你的代码库抛出时,这些方法是不恰当的称为异常,不会是其他类的真的,你正在使用,无论从JDK或第三方库.
我相信你可以用某种形式或其他形式的AOP做到这一点,无论是正常的注释处理还是别的 - 但你有证据表明奖励是值得的吗?
看它的另一种方法:这是只有在你延伸的覆盖已经另一个类的情况下hashCode和equals,对不对?否则,您可以使用Object的hashCode/equals方法的"equality = identity"特性,这仍然有用.你有很多属于这一类的课程吗?您是否可以通过反射编写单元测试以查找所有此类类型,并在调用hashCode/ 时检查这些类型是否会引发异常equals?(如果它们具有无参数构造函数,或者具有已检查的类型的手动列表,则可以自动执行 - 如果存在不属于"已知商品"列表的新类型,则单元测试可能会失败.)
我不明白为什么你认为"在某些情况下你不能满足等于()合同"?等式的含义由类定义.因此,使用Object等于完全有效.如果您没有覆盖equals,那么您将每个实例定义为唯一.
似乎存在一种误解,即equals是总是需要覆盖的那些方法之一,并且必须检查其所有字段.我认为相反 - 除非你的平等定义不同,否则不要重写等于.
我也不同意artima的文章,特别是"陷阱#3:根据可变领域定义平等".对于一个基于可变字段定义其相等性的类来说,它是完全有效的.当用户将其与集合一起使用时,用户需要注意这一点.如果一个可变对象在其可变状态上定义了它的相等性,那么在一个实例改变之后不要指望两个实例是等于的.
我认为抛出UnsupportedOperation违反了平等的冲刺.对象等于状态:
类Object的equals方法实现了对象上最具辨别力的等价关系; 也就是说,对于任何非空引用值x和y,当且仅当x和y引用同一对象时,此方法才返回true(x == y的值为true).
因此,我应该能够调用equals并获取true或false值,具体取决于Object的equals定义或重写的equals定义.
为什么不让您的 IDE (Eclipse/NetBeans/IntelliJ)为您生成hashCode()和方法。equals()他们在这方面做得很好。
当然,AOP 可以工作,但它相当复杂。这意味着您将无法在几乎没有集合或实用程序的情况下使用这些对象。
另一个合乎逻辑的解决方案是删除那些不起作用的方法的实现,从而有效地仅保留Object.
| 归档时间: |
|
| 查看次数: |
6967 次 |
| 最近记录: |