为什么可以Object.=比较不能与引用相等操作符(==)比较的类型?



我知道在Java中不能使用==比较两个不相关的实例,因为它会产生编译错误(不兼容的类型)。例如

class Animal {}
class Dog extends Animal {}
class Cat extends Animal {}
Dog d = new Dog();
Cat c = new Cat();
System.out.println( d == c );

是编译时错误。

但是为什么使用从Object继承的等号不会产生这种错误呢?

System.out.println( d.equals(c) );  // is false

即使Object.equals内部使用==?

现在,我知道为什么它是false,但我不知道为什么它不是错误,因为签名是:

public boolean equals(Object obj) {
return (this == obj);
}

因为在Object#equals内部比较的类型都是Object,因此==操作符是"允许的"。

请记住,大多数时候不要使用==或默认的Object#equals进行比较,因为它比较的是引用,而不是内容。见https://stackoverflow.com/questions/7520432/what-is-the-difference-between-and-equals-in-java?r=SearchResults& s = 3 | 156.7237

编译时检查在引用相等的位置执行-在Object.equals内。在您引用的Object.equals方法的上下文中,它将thisObject进行比较:

public boolean equals(Object obj) {
return (this == obj);
}

根据Java语言规范:

如果无法通过强制转换将其中一个操作数的类型转换为另一个操作数的类型,则会出现编译时错误(第5.5节)。两个操作数的运行时值必然不相等(忽略两个值都为null的情况)。

由于this可以强制转换为Object,因此this == obj是对引用相等运算符(==)的有效使用,因此它可以编译。


作为一个实际的例子,观察Java API中的一个案例,其中两个对象不能通过引用相等(==)进行比较,但是通过Object.equals进行比较时它们是相等的。

首先,注意Object.equals的实现只是equals基础实现。如果合适的话,建议Object的子类使用不同的实现。 其次,请注意,与引用相等操作符(==)不同,equals方法对两个比较对象是否可以转换为另一个对象的类型没有限制。根据Object.equals的Javadocs,这两个对象只需要实现一个等价关系:

equals方法实现了对非空对象引用的等价关系:

  • 是自反的:对于任何非空的参考值x,x.equals(x)应该返回true
  • 对称:对于任何非空参考值xy,当且仅当y.equals(x)返回true时,x.equals(y)应该返回true
  • 可传递:对于任何非空参考值x,yz,如果x.equals(y)返回true,y.equals(z)返回true,那么x.equals(z)应该返回true
  • 一致:对于任何非空的参考值xy,多次调用x.equals(y)一致地返回true或一致地返回false,前提是在equals比较对象时使用的信息没有被修改。
  • 对于任何非空的参考值x,x.equals(null)应该返回false

以JavaList接口为例。它指定了实现类必须如何实现equals:

将指定对象与此列表进行比较是否相等。当且仅当指定的对象也是一个列表,两个列表具有相同的大小,并且两个列表中所有对应的元素对等于时返回true。(两个元素e1e2等于如果Objects.equals(e1, e2)。)换句话说,如果两个列表以相同的顺序包含相同的元素,则定义为相等。这个定义确保了equals方法可以在不同的List接口实现中正常工作。

现在,以两个不能相互强制转换的列表为例,如ArrayListLinkedList。不能使用引用相等错误(==)将LinkedList引用与ArrayList引用进行比较,因为这两种类型都不能强制转换为另一种类型。另一方面,如果ArrayList包含相同顺序的相同元素,则.equalsLinkedList

ArrayList<String> a = new ArrayList<String>(Arrays.asList("X", "Y", "Z"));
LinkedList<String> b = new LinkedList<String>(Arrays.asList("X", "Y", "Z"));
assert a.equals(b); // true
assert a == b; // compiler error

最新更新