陷阱 - 重载而不是覆盖

请考虑以下示例:

public final class Person {
    private final String firstName;
    private final String lastName;
   
    public Person(String firstName, String lastName) {
        this.firstName = (firstName == null) ? "" : firstName;
        this.lastName = (lastName == null) ? "" : lastName;
    }

    public boolean equals(String other) {
        if (!(other instanceof Person)) {
            return false;
        }
        Person p = (Person) other;
        return firstName.equals(p.firstName) &&
                lastName.equals(p.lastName);
    }

    public int hashcode() {
        return firstName.hashCode() + 31 * lastName.hashCode();
    }
}

此代码不会按预期运行。问题是 Personequalshashcode 方法不会覆盖 Object 定义的标准方法。

  • equals 方法签名错误。它应该被声明为 equals(Object) 而不是 equals(String)
  • hashcode 方法名称错误。它应该是 hashCode()(注意大写字母 C )。

这些错误意味着我们已经声明意外重载,如果在多态上下文中使用 Person,则不会使用这些错误。

但是,有一种简单的方法可以解决这个问题(从 Java 5 开始)。每当你使用 @Override 注解打算你的方法是一个覆盖:

Version >= Java SE 5

public final class Person {
    ...

    @Override
    public boolean equals(String other) {
        ....
    }

    @Override
    public hashcode() {
        ....
    }
}

当我们将 @Override 注释添加到方法声明时,编译器将检查该方法是否覆盖(或实现)在超类或接口中声明的方法。所以在上面的例子中,编译器会给我们两个编译错误,这应该足以提醒我们错误。