gpt4 book ai didi

equals() 中的 Java 类型检查 : instanceof vs getClass()

转载 作者:行者123 更新时间:2023-11-30 07:07:56 25 4
gpt4 key购买 nike

首先,我并不是询问它们之间的区别。

我心里有一个想法,我想要更多的大脑来验证,这似乎能够发挥(大部分)使用这两种方法的优点。

简而言之,Java 中的 equals() 通常如下所示。

public boolean equals(Object other) {
if (other == null) return false;
if (this == other) return true;
if (this and other is not of the same type) return false
// then actual equals checking
}

问题在于“这个和其他不是同一类型”检查。

有一类人更喜欢使用if (!(other instanceof MyClass)),它有一个缺点

  • 容易导致结果不对称。如果 other 是 MyClass 的子类并且重写了 equals()a.equals(b)b.equals(a ) 不会相同
  • 为了避免这种情况,我们需要通过将其声明为final来避免子类重写equals()

另一类人更喜欢使用if (getClass() != other.getClass()),它有一个缺点

  • 违反里氏替换原则。 MyClass 的子类应该能够代替 MyClass 使用。
  • 因此,如果 a 属于 MyClassb 属于MyClass 的子类,连内部属性都一样。
<小时/>

我心中有一个想法,希望人们验证。

这种方法应该

  1. 如果子类重写了 equals(),结果仍应是对称的
  2. 子类仍然可以用作其父类型(在 equals() 方面,并且 equals 当然不会被覆盖)

    public class Parent {
    @Override
    public boolean equals(Object other) {
    if (other == null) return false;
    if (this == other) return true;
    if (!(other instanceof Parent)) return false;
    try {
    if (other.getClass().getMethod("equals", Object.class).getDeclaringClass() != Parent.class) {
    return other.equals(this);
    }
    } catch(Exception neverHappen){}

    // do actual checking
    }
    }

主要思想是,如果this遇到一个Parent对象,但该对象的equals()未在Parent中声明 (即该对象是一个子类,并覆盖了 equals() ,我将把 equals 调用委托(delegate)给子类对象(或者可能只是返回 false )。

使用这种方法是否有任何我忽略的缺点? (我猜性能损失将是一个问题,但我相信调用 getClass().method("equals").getDeclaringClass() 应该相当便宜?)

最佳答案

正如评论中所述,如果子类这样做 super.equals(..) ,你会得到一个 stackoverflow。为了防止这种情况,你最终会重写整个 parent equals(..)在每个 child 身上,这是最糟糕的设计。

不知何故,这取决于您首先如何/为何实现继承。 child 应该与 parent 相媲美吗?比较有意义吗? (已编辑)

如果您覆盖 equals,那么根据定义,您就不尊重 LSP。如果子级有更多参数(这意味着它覆盖了 equals 方法),那么它不应该等于其父级,这就是为什么我们可以使用 getClass() != other.getClass() 进行比较在父级中。如果想使用父类的equals()在你的 child 中(所以你不必全部重写),你不会最终出现堆栈溢出; equals()只会是错误的,因为它们本来就不是平等的。

如果一个 child 与其 parent 具有可比性怎么办?如果您尊重 LSP, child 就不应该有不同的equals()我猜比他的 parent (即: equals 不应该被覆盖)。所以不对称的情况不应该存在。

如果一个 child 与其 parent 相当,但有更多参数?现在这是您的设计,不尊重 LSP,因此您需要了解它在您的上下文中的含义并采取相应的行动。

<小时/>

编辑:@Adrian 是的,“对称性有意义吗”是糟糕的措辞,我应该说“比较有意义吗?”。

对于您的示例,如果您将两个子类与 getClass() 进行比较他们还使用 super getClass()它将返回 true (测试将是重复的,因为 this.getClass()other.getClass() 在子级和父级中始终具有相同的值)。但正如我所说,如果你比较 child 和 parent ,那将是错误的(我认为如果他们有不同的参数,这是正常的)。

为什么仅在 equals 和 of 的实例上使用final?你这么说是因为可能存在不对称,而使用 getClass() 继承是不可能不对称的。 ,所以在这种情况下将其定为最终版本是没有用的。

作为旁注,如果您使用 getClass() ,那么同一父级的多个子级将不具有可比性(始终返回 false )。如果您使用instanceof ,他们可以,但如果他们这样做,任何 child 都不应覆盖 equals()因为有破坏对称性的风险。 (我想你明白了,但我想知道什么时候选择 insteanceof 而不是 getClass() 如果它有问题的话)。

关于equals() 中的 Java 类型检查 : instanceof vs getClass(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39766245/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com