当我读一本 Java 书籍时,作者曾说过,在设计类时,使用继承的 equals()
通常是不安全的。例如:
public final class Date {
public boolean equals(Object o) {
// some code here
}
}
在上面的类中,我们应该放置final
,这样其他类就不能继承自它。我的问题是,为什么允许另一个类继承自它是不安全的?
最佳答案
因为很难(不可能?)让它正确,尤其是 symmetric property .
假设您有 Vehicle
类和 Car extends Vehicle
类。如果参数也是 Vehicle
并且具有相同的权重,则 Vehicle.equals()
产生 true
。如果你想实现 Car.equals()
它应该只在参数也是汽车时产生 true
,除了重量,它还应该比较品牌,引擎等.
现在想象下面的代码:
Vehicle tank = new Vehicle();
Vehicle bus = new Car();
tank.equals(bus); //can be true
bus.equals(tank); //false
如果碰巧坦克和公共(public)汽车具有相同的重量,第一次比较可能会产生 true
。但由于坦克不是汽车,将它与汽车进行比较总是会得出 false
。
您几乎没有解决方法:
strict:两个对象相等当且仅当它们具有完全相同的类型(并且所有属性都相等)。这很糟糕,例如当您几乎不添加一些行为或装饰原始类时。一些框架也在您不注意的情况下对您的类进行子类化(Hibernate、带有 CGLIB 代理的 Spring AOP...)
松散:如果两个对象的类型“兼容”并且具有相同的内容(语义上),则这两个对象是相等的。例如。如果两个集合包含相同的元素,则它们是相等的,一个是
HashSet
另一个是TreeSet
并不重要(感谢 @veer指出这一点)。这可能会产生误导。取两个
LinkedHashSet
(其中插入顺序作为契约(Contract)的一部分很重要)。然而,由于equals()
仅考虑原始Set
契约(Contract),因此即使对于明显不同的对象,比较也会产生true
:Set<Integer> s1 = new LinkedHashSet<Integer>(Arrays.asList(1, 2, 3)); Set<Integer> s2 = new LinkedHashSet<Integer>(Arrays.asList(3, 2, 1)); System.out.println(s1.equals(s2));
关于java - 为什么我不应该将 equals 与继承一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12239344/