简体   繁体   English

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

[英]Why doesn't Java's `equals()` do deep comparison by default

It is well-known that the equals() method of an object, if not overridden, is a "shallow comparison" that is equivalent to using the "==" operator. 众所周知,对象的equals()方法如果不被覆盖,则是“浅比较”,等同于使用“==”运算符。 (See, for example, https://docs.oracle.com/javase/tutorial/java/IandI/objectclass.html .) (例如,参见https://docs.oracle.com/javase/tutorial/java/IandI/objectclass.html 。)

Question: why doesn't Java provide a "deep-comparison" equals() method by default? 问题:为什么Java默认情况下不提供“深度比较” equals()方法? That is, one that will invoke equals() on each of its instance variables recursively. 也就是说,将以递归方式对每个实例变量调用equals() Eventually, the recursion will reach primitive types and stop. 最终,递归将达到原始类型并停止。 Are there any downsides if this deep-comparison equals was the default? 如果这种深度比较等于默认值,是否有任何缺点?

Are there any downsides if this deep-comparison equals was the default? 如果这种深度比较等于默认值,是否有任何缺点?

Yes. 是。 These include: 这些包括:

  • The default implementation cannot distinguish between references that are part of the logical value of the object, and references that are just associations with other objects. 默认实现无法区分作为对象逻辑值一部分的引用,以及仅与其他对象关联的引用。 For example, say you have a Person class that references a company. 例如,假设您有一个引用公司的Person类。 You have two Person instances with the same name, SSN, DOB, etc. One references an old company. 您有两个具有相同名称的Person实例,SSN,DOB等。一个引用旧公司。 You may want the two Person instances, that reference the same actual person, to be equal, even though one has an outdated association. 您可能希望引用相同实际人员的两个Person实例相等,即使其中一个具有过时关联。
  • A deep equality test would frequently be slower than the current default, possibly significantly slower. 深度相等测试通常比当前默认测试慢,可能明显更慢。 Frequently this would be unnecessary. 通常这是不必要的。 The current default insures that the equality test is always fast unless someone specifies otherwise explicitly. 当前的默认值确保相等测试总是很快,除非有人明确指定。
  • A deep comparison would need to handle cycles in the references. 深度比较需要处理引用中的循环。 This would require some way to remember what objects had already been traversed. 这需要一些方法来记住已遍历的对象。 This would require memory to track those objects, potentially a significant amount of memory. 这将需要内存来跟踪这些对象,可能需要大量内存。 An equality test could lead to an OutOfMemoryError. 相等测试可能导致OutOfMemoryError。

The current default implementation is fast and makes no assumptions. 当前的默认实现很快,不做任何假设。 It's a good default. 这是一个很好的默认值。 Sometimes you will need to override the default, using your knowledge about what the logical value of the object contains, regardless of its root physical representation. 有时,您将需要使用您对对象的逻辑值包含的内容的了解来覆盖默认值,而不管其根物理表示形式如何。

A deep compare is much more complex and time consuming than a comparison of two references. 与两个引用的比较相比,深度比较要复杂得多,也要耗费时间。 This might be ok for simple objects, but when you have really complex data structures (eg a tree with ten thousand elements) how should the system know how "deep" the compare should be? 这对于简单对象可能没问题,但是当你有非常复杂的数据结构时(例如一棵有一万个元素的树),系统应该如何知道比较应该“深入”?

For most objects reference equality is the correct implementation. 对于大多数对象,引用相等是正确的实现。 "Deep" equals is for the minority that maintain state. “深层”等于维持国家的少数民族。 Not only would your proposal run into the problems many here described, it would be wrong for most types. 您的提案不仅会遇到许多此处描述的问题,对大多数类型而言都是错误的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM