skip to content

Search

Object

4 min read Updated:
海滩

关于Object类和方法

equals

equals方法在Object类中定义为比较两个对象的引用是否相等

重写时必须遵循以下规则:

  • 自反性:x.equals(x)必须返回true
  • 对称性:x.equals(y)为true当且仅当y.equals(x)为true
  • 传递性:x.equals(y)为true,y.equals(z)为true,则x.equals(z)必须为true
  • 一致性:多次调用x.equals(y)必须始终返回true或始终返回false

实现equals方法时建议如下:

  1. 显式参数为Object otherObject
  2. 检查this == otherObject
  3. 检查otherObject是否为null
  4. 比较this和otherObject的类,分两种情况
  • 如果子类改变了父类的equals方法,则父类必须使用getClass()来比较类
  • 如果所有的子类相等性语义相同,则父类可以使用instanceof来比较类
  1. 将otherObject强制转换为当前类类型,比较对应字段是否相等

常见的错误在于子类添加了新的字段,父类的equals方法使用instanceof来比较类 由于子类要检查额外字段,必须将otherObject强制转换为子类类型,在此之前使用instanceof检查类型,传入的父类参数就不成立

// 父类
class Employee {
    @Override
    public boolean equals(Object o) {
        if (!(o instanceof Employee)) return false;
        // 检查剩余字段...
    }
}
 
// 子类(增加字段)
class Manager extends Employee {
    @Override
    public boolean equals(Object o) {
        if (!super.equals(o)) return false;      // 父类检查通过
        if (!(o instanceof Manager)) return false; // 关键检查,不通过
        // 检查子类剩余字段...
    }
}

此时employee.equals(manager)为true,但manager.equals(employee)为false,违反了对称性。

hashCode

hashCode方法在Object类中定义为返回对象的哈希码,是由对象的内存地址计算得出的一个整数值。

重写equals方法时,必须同时重写hashCode方法,以确保相等的对象具有相同的哈希码。

可以使用Objects.hash(Object... values)方法来生成哈希码

public class Person {
    private String name;
    private int age;
    private double salary;
 
    @Override
    public int hashCode() {
        // 直接把 equals 里用到的所有字段扔进去即可
        return Objects.hash(name, age, salary);
    }
}

Objects.hash调用Arrays.hashCode方法来计算哈希码,Arrays.hashCode方法将各元素的哈希值乘以31的幂次方后相加

// Objects.hash(Object... values) 方法的实现
public static int hash(Object... values) {
        return Arrays.hashCode(values);
    }
// Arrays.hashCode(Object[] a) 方法的实现
public static int hashCode(Object a[]) {
        if (a == null)
            return 0;
        int result = 1;
        for (Object element : a)
            result = 31 * result + (element == null ? 0 : element.hashCode());
        return result;
    }

toString

toString方法在Object类中定义为返回对象的字符串表示形式,默认实现返回对象的 类名@哈希码

// Object.toString() 方法的实现
public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }
  • 当对象与字符串拼接时,toString方法会被自动调用。

    "str" + obj等价于"str" + obj.toString()

  • 当对象被打印时,打印的就是toString方法的返回值 System.out.println(obj)等价于System.out.println(obj.toString())

建议恰当重写toString方法,以提供对象的有意义的字符串表示形式,便于调试和日志记录。