2个不同类的Java对象是否应该相等?

tho*_*8wp 22 java

我正在尝试编写一些通用代码来定义基于字段列表的类相等和哈希码.在编写我的equals方法时,我想知道,基于Java约定,两个不同的对象是否应该是相同的.让我举几个例子;

class A {
  int foo;
}
class B {
  int foo;
}
class C extends A {
  int bar;
}
class D extends A {
  void doStuff() { }
}
...
A a = new A(); a.foo = 1;
B b = new B(); b.foo = 1;
C c = new C(); c.foo = 1; c.bar = 2;
D d = new D(); d.foo = 1;

a.equals(b); //Should return false, obviously
a.equals(c);
c.equals(a); //These two must be the same result, so I'd assume it must be false, since c cant possible equal a
a.equals(d); //Now this one is where I'm stuck. 
Run Code Online (Sandbox Code Playgroud)

我认为没有理由在最后一个例子中两者不应该相等,但它们确实有不同的类.有人知道会议的规定吗?如果他们是平等的,那么equals方法应如何处理呢?

编辑:如果有人对这个问题背后的代码感兴趣,请参阅:https://gist.github.com/thomaswp/5816085这有点脏,但我欢迎对要点发表评论.

And*_*yle 22

它们可能是,但在这种情况下通常很难保持相等的对称性和传递性.至少在有一个有用/直观的平等定义时.

如果允许子类认为自己等于超类的实例,那么超类需要认为自己等于子类的实例.这意味着你将在超类中编码关于子类(所有可能的子类?)的特定知识,并根据需要进行向下转换,这不是很干净.

或者,您仅使用包含的字段进行比较A,并且根本不覆盖equals().这解决了上面的问题,但是有两个C具有不同值的实例bar被认为是相等的问题,这可能不是你想要的.

或者,你覆盖in C,并比较bar另一个对象是否是一个实例C,否则不是一个实例A,你有另一个问题. c1.equals(c2)会是假的,但是c1.equals(a)会是c2.equals(a)如此a.equals(c2).这打破了传递性(c1 == a从而a == c2暗示c1 == c2).


总之,它在理论上是可行的,但你必须削弱你的equals实现才能这样做.此外,运行时类是对象的属性bar,因此我希望具有不同具体类的对象无论如何都不会彼此相等.

  • `LinkedList`s和`ArrayList`可以肯定(并且合理地)"相等". (3认同)