提问人:saga 提问时间:9/19/2021 最后编辑:M. Justinsaga 更新时间:11/28/2021 访问量:1120
为什么 Object.equals 可以比较无法与引用相等运算符 (==) 比较的类型?
Why can Object.equals compare types that cannot be compared with the reference equality operator (==)?
问:
我知道在 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
this
Object
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
方法对两个比较对象是否可以转换为另一个对象的类型没有限制。根据 的 Javadocs,这两个对象只需要实现一个等价关系:==
Object.equals
该方法在非 null 对象引用上实现等价关系:
equals
- 它是自反的:对于任何非空引用值,应返回 。
x
x.equals(x)
true
- 它是对称的:对于任何非空引用值和 ,应返回当且仅当返回 。
x
y
x.equals(y)
true
y.equals(x)
true
- 它是可传递的:对于任何非空引用值,和 ,如果返回 和 返回 ,则应返回 。
x
y
z
x.equals(y)
true
y.equals(z)
true
x.equals(z)
true
- 它是一致的:对于任何非空引用值和 ,只要没有修改对象比较中使用的信息,就会多次调用一致返回或一致返回。
x
y
x.equals(y)
true
false
equals
- 对于任何非空引用值,应返回 。
x
x.equals(null)
false
以 Java List
接口为例。它指定实现类必须如何实现 equals:
将指定的对象与此列表进行比较,以确保相等。当且仅当指定的对象也是列表,两个列表具有相同的大小,并且两个列表中所有对应的元素对都相等时,才返回。(两个元素相等,如果。换句话说,如果两个列表以相同的顺序包含相同的元素,则它们被定义为相等。此定义可确保 equals 方法在接口的不同实现中正常工作。
true
e1
e2
Objects.equals(e1, e2)
List
现在,获取两个无法相互强制转换的列表,例如 ArrayList
和 LinkedList
。不能使用引用相等误差 () 将引用与引用进行比较,因为这两种类型都不能强制转换为另一种类型。另一方面,如果它们以相同的顺序包含相同的元素,则 an 将是 a。LinkedList
ArrayList
==
ArrayList
.equals
LinkedList
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
评论
Object#equals
Object
equals
equals
equals