在生成 .equals() 时,有什么理由更喜欢 getClass() 而不是 instanceof?

2022-08-31 06:31:21

我正在使用Eclipse来生成和,并且有一个标有“使用'instanceof'比较类型”的选项。默认设置是取消选中此选项,并用于比较类型。有什么理由我应该更喜欢吗?.equals().hashCode().getClass().getClass()instanceof

不使用 :instanceof

if (obj == null)
  return false;
if (getClass() != obj.getClass())
  return false;

用:instanceof

if (obj == null)
  return false;
if (!(obj instanceof MyClass))
  return false;

我通常会检查该选项,然后进入并删除“”检查。(这是多余的,因为空对象总是会失败。有什么理由这是一个坏主意吗?instanceofif (obj == null)instanceof


答案 1

Josh Bloch支持你的方法:

我赞成这种方法的原因是,当您使用该方法时,您有一个限制,即对象仅等于同一类,相同运行时类型的其他对象。如果你扩展一个类,并给它添加几个无害的方法,然后检查子类的某些对象是否等于超类的对象,即使这些对象在所有重要方面都是相等的,你也会得到一个令人惊讶的答案,即它们不相等。事实上,这违反了对里氏替换原理的严格解释,并可能导致非常令人惊讶的行为。在Java中,它尤其重要,因为大多数集合(等)都是基于equals方法的。如果将超类的成员作为键放在哈希表中,然后使用子类实例查找它,则不会找到它,因为它们不相等。instanceofgetClassHashTable

另请参阅此 SO 答案

有效的 Java 第 3 章也涵盖了这一点。


答案 2

如果使用 ,则使实现将保留方法的对称协定:。如果看起来有限制性,请仔细检查对象等价的概念,以确保重写实现完全维护类建立的协定。instanceofequalsfinalx.equals(y) == y.equals(x)finalObject


我在这里试图说的是,如果你认为这是保持对称性的唯一可靠方法,那么你可能使用了错误的方法。getClass()equals()

当然,它很容易用于保持 所需的对称性,但这只是因为 和 总是假的。Liskov可替代性会鼓励你找到一个保持对称性的实现,当它有意义时可以屈服。如果一个子类具有完全不同的平等概念,那么它真的是一个子类吗?getClass()equals()x.equals(y)y.equals(x)true


推荐