为什么Java的#equals()`默认情况下不进行深度比较

时间:2017-06-26 21:39:36

标签: java equals

众所周知,对象的equals()方法如果不被覆盖,则是一个浅层比较"这相当于使用" =="运营商。 (例如,参见https://docs.oracle.com/javase/tutorial/java/IandI/objectclass.html。)

问题:为什么Java没有提供深度比较"默认情况下为equals()方法?也就是说,将递归地在每个实例变量上调用equals()。最终,递归将达到原始类型并停止。如果这种深度比较等于默认值,是否有任何缺点?

3 个答案:

答案 0 :(得分:10)

  

如果这种深度比较等于默认值,是否有任何缺点?

是。其中包括:

  • 默认实现无法区分作为对象逻辑值一部分的引用,以及仅与其他对象关联的引用。例如,假设您有一个引用公司的Person类。您有两个具有相同名称的Person实例,SSN,DOB等。一个引用旧公司。您可能希望引用相同实际人员的两个Person实例相等,即使其中一个具有过时关联。
  • 深度相等测试通常比当前默认测试慢,可能会慢得多。通常这是不必要的。当前的默认值确保了相等测试总是很快,除非有人明确指定。
  • 深度比较需要处理引用中的循环。这需要一些方法来记住已遍历的对象。这将需要内存来跟踪这些对象,可能需要大量内存。相等测试可能导致OutOfMemoryError。

当前的默认实现很快,不做任何假设。这是一个很好的默认值。有时您需要使用您对对象的逻辑值包含的内容的知识来覆盖默认值,而不管其根物理表示形式。

答案 1 :(得分:3)

深度比较比两个引用的比较要复杂得多,也要耗费时间。这对于简单的对象可能没问题,但是当你有非常复杂的数据结构时(例如一棵有一万个元素的树),系统应该知道比较应该“深入”多少?

答案 2 :(得分:0)

对于大多数对象,引用相等是正确的实现。 "深"等于维持国家的少数民族。您的提案不仅会遇到许多此处描述的问题,对大多数类型来说都是错误的。