为什么 NetBean 的自动生成的等于如此冗长?



当NetBeans自动生成equals方法时,它以以下形式:

@Override
public boolean equals(Object obj) {
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    final MyClass other = (MyClass)obj;
    if (!Object.equals(this.field, other.field))
        return false;
    return true;
}

这看起来很啰嗦。Java的instanceofnull值返回false,所以为什么不将初始测试简化为:

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

我也不清楚为什么这段代码会显式地在字段比较中使用this.field(大概是为了避免混淆),但出于同样的原因不会使用this.getClass() ?

NetBean的形式有什么优势吗?

instanceof和类比较有大的差异。请记住(例如)HashMap实例是instanceof AbstractMap,但如果AbstractMapequals实际上是HashMap,则不应考虑otherAbstractMapinstanceof测试允许类型或其任何子类型的实例,因此不是对称的。equals要求对称。(下面的例子。)

Netbeans代码确实看起来相当呆板,可以写得更简洁,但是按照给定的顺序,这些操作作为默认起点是有意义的。(不过我会附上this支票。)这对类很少有equal实例,所以使用getClass作为默认实现是合理的。

只是提醒我们所有的合同:

  • 是自反性:对于任何非null的参考值x, x.equals(x)应该返回true
  • 对称:对于任何非null的参考值xy,当且仅当y.equals(x)返回true时,x.equals(y)应该返回true
  • 可传递:对于任何非null的参考值xyz,如果x.equals(y)返回true, y.equals(z)返回true,那么x.equals(z)应该返回true
  • 一致:对于任何非null参考值x and y , multiple invocations of x.equals(y) consistently return true or consistently return false , provided no information used in equals对对象的比较被修改
  • 对于任何非null的参考值x, x.equals(null)应该返回false

在90年代早期的Java时代,我打破了这个契约(无意中),根据对这个问题的回答,我不是唯一的一个。我使用instanceof(和super.equals),如下所示:

class Parent {
    private int foo;
    protected int getFoo() {
        return foo;
    }
    Parent(int f) {
        this.foo = f;
    }
    // ...
    @Override
    public boolean equals(Object obj) {
        // WRONG, see below
        if (obj == this) {
            return true;
        }
        if (!(obj instanceof Parent)) {
            return false;
        }
        return this.foo == ((Parent)obj).foo;
    }
}
class Child extends Parent {
    private int bar;
    Child(int f, int b) {
        super(f);
        this.bar = b;
    }
    // ...
    @Override
    public boolean equals(Object obj) {
        // WRONG, see below
        if (obj == this) {
            return true;
        }
        if (!(obj instanceof Child)) {
            return false;
        }
        return super.equals(obj) && this.bar == ((Child)obj).bar;
    }
}

这里的问题是它不是对称的:

Parent p = new Parent(1);
Child  c = new Child(1, 2);
System.out.println(p.equals(c)); // true
System.out.println(c.equals(p)); // false

这违反了合同。

相关内容

  • 没有找到相关文章

最新更新