Java .equals()instanceof子类?为什么不调用超类等于而不是使其最终化呢? [英] Java .equals() instanceof subclass? Why not call superclass equals instead of making it final?

查看:91
本文介绍了Java .equals()instanceof子类?为什么不调用超类等于而不是使其最终化呢?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Object的 .equals(Object) javadoc中进行了说明:

It is stated in Object's .equals(Object) javadoc:


它是对称的:对于任何非空参考值x和y,当且仅当y.equals(x)返回
true时,
x.equals(y)才应返回true。

It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.

在示例代码中几乎所有地方我都看到覆盖了 .equals(Object)方法,该方法使用 instanceof 作为第一个测试之一,例如:在重载等于和hashCode时必须考虑哪些问题/陷阱?

Almost everywhere in example code I see overridden .equals(Object) method which uses instanceof as one of the first tests, for example here: What issues / pitfalls must be considered when overriding equals and hashCode?

public class Person {
    private String name;
    private int age;

    public boolean equals(Object obj) {
        if (obj == null)
            return false;
        if (obj == this)
            return true;
        if (!(obj instanceof Person))
            return false;
        ...
    }

}

现在具有类的SpecialPerson扩展了具有等式的Person

Now with class SpecialPerson extends Person having in equals:

        if (!(obj instanceof SpecialPerson))
            return false;

我们不保证 .equals()是对称的。
此处已进行了讨论,例如: any-reason-to-prefer-getclass-over-instanceof-when-generating-等于

we con not guarantee that .equals() is symmetric. It has been discussed for example here: any-reason-to-prefer-getclass-over-instanceof-when-generating-equals

Person a = new Person(), b = new SpecialPerson();

a.equals(b);    //sometimes true, since b instanceof Person
b.equals(a);    //always false

也许我应该在SpecialPerson的equals开头直接添加对super的输入?

Maybe I should add in the beginning of SpecialPerson's equals direct call to super?

    public boolean equals(Object obj) {
        if( !obj instanceof SpecialPerson )
            return super.equals(obj);
        ... 
        /* more equality tests here */
    }


推荐答案

很多示例出于以下两个原因而使用 instanceof :a)折叠null检查并将type检查折叠为一个或b)该示例适用于Hibernate或其他代码重写框架。

A lot of the examples use instanceof for two reasons: a) it folds the null check and type check into one or b) the example is for Hibernate or some other code-rewriting framework.

正确(根据JavaDoc)解决方案是使用 this.getClass()== obj.getClass()。这适用于Java,因为类是单例,并且VM保证了这一点。如果您偏执狂,可以使用 this.getClass()。equals(obj.getClass()),但两者实际上是等效的。

The "correct" (as per the JavaDoc) solution is to use this.getClass() == obj.getClass(). This works for Java because classes are singletons and the VM guarantees this. If you're paranoid, you can use this.getClass().equals(obj.getClass()) but the two are really equivalent.

这在大多数情况下都有效。但是有时,Java框架需要使用字节码来巧妙地处理事情。这通常意味着它们会自动创建一个子类型。由于应该将子类型视为与原始类型相同,因此必须以错误方式实现 equals(),但这无关紧要,因为在运行时,子类型将全部遵循某些模式。例如,他们将在调用setter之前做其他事情。

This works most of the time. But sometimes, Java frameworks need to do "clever" things with the byte code. This usually means they create a subtype automatically. Since the subtype should be considered equal to the original type, equals() must be implemented in the "wrong" way but this doesn't matter since at runtime, the subtypes will all follow certain patterns. For example, they will do additional stuff before a setter is being called. This has no effect on the "equalness".

正如您所注意到的,当同时遇到两种情况时,事情开始变得很难看:您实际上扩展了基本类型,然后将它们混合使用自动生成子类型。如果这样做,则必须确保不要使用非叶子类型。

As you noticed, things start to get ugly when you have both cases: You really extend the base types and you mix that with automatic subtype generation. If you do that, you must make sure that you never use non-leaf types.

这篇关于Java .equals()instanceof子类?为什么不调用超类等于而不是使其最终化呢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆