Java 常用类之 Object

1、Object 类

Object 类是 Java 中所有类的始祖,我们可以使用 Object 类型的变量引用任何类型的对象。在 Java 中,只有基本类型不是对象。
注意:数组也是对象,我们可以把它赋值给 Object 类型的变量,也可以通过数组对象调用 Object 类中的方法,如下所示。

public class Main {
    public static void main(String[] args) {
        int[] arr = new int[10];
        Object obj = arr;
        System.out.println(arr.equals(new int[10]));
    }
}

基本类型由于自动装箱也可以赋值给 Object 类型的变量。

2、equals 方法

Object 类中的 equals方法比较两个对象的引用是否相等,源码如下:

public boolean equals(Object obj) {
    return (this == obj);
}

而我们通常需要比较两个对象的状态是否相等,这就需要我们覆盖 Object 类中的 equals 方法。

下面使用 Employee 类举例,给出比较通用的覆盖方法:

class Employee {
    private String name;
    private double salary;

    public Employee(String name, double salary) {
        this.name = name;
        this.salary = salary;
    }

    @Override
    public boolean equals(Object otherObject) {
        // 1.判断对象的引用是否相等
        if(this == otherObject) return true;

        // 2.判断 otherObject 是否为 null
        if(otherObject == null) return false;

        // 3.判断 this 与 otherObject 的类型是否相等
        if(getClass() != otherObject.getClass()) return false;

        // 4.将 otherObject 强制类型转换为相应的类型
        Employee other = (Employee) otherObject;

        // 5.使用 == 比较基本类型,使用 Object.equals 比较引用类型
        return Objects.equals(name, other.name)
                && salary == other.salary;
    }
}

特别注意

  • 在第三个判断语句中,两个对象如果类型不同就会返回 false。但是,是否这样实现取决于具体的情况。如果子类判断相等的方式和父类一致,我们可以不强求类型相同,这时使用if(!(otherObject instanceof Employee)) return false;语句替换。
  • 在最后的 return 语句中,我们比较 name 对象需要使用Objects.equals,而不能使用name.equals(other.name)。这是因为当 name 为 null 时,使用后一种方式会导致空指针异常
  • 如果在子类中重新定义 equals 方法,我们需要在return语句中包含super.equals(other)调用,来判断父类中的字段是否相同。

补充:对于数组类型的字段,可以使用静态的Arrays.equals方法判断对应的数组元素是否相等。

3、hashCode 方法

Object 类中的 hashCode方法是本地方法,它根据对象的存储地址计算得出散列码。

@IntrinsicCandidate
public native int hashCode();

如果我们重新定义了 equals 方法,那么就要为可能插入散列表的对象重新定义 hashCode 方法。且 equals 与 hashCode 的定义必须相容:如果 x.equals(y) 返回 true,那么 x.hashCode() 就必须与 y.hashCode() 相等。

我们可以使用Objects.hashCodeObjects.hash方法为自定义类计算散列码。

补充:对于数组类型的字段,可以使用静态的Arrays.hashCode方法计算散列码,这个散列码由数组元素的散列码组成。

4、toString 方法

Object 类中的toString方法返回的是对象的类名和散列码组成的字符串,如下所示:

public String toString() {
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

一般而言,我们应该为每个自定义的类覆盖 toString 方法,格式如下:

@Override
public String toString() {
    return getClass().getName()
            + "[name=" + name
            + ", salary=" + salary
            + "]";
}

最好通过调用getClass().getName()获取类名字符串,而不要将类名硬编码到 toString 方法中。这样子类调用父类的 toString 方法时,将会获取子类的类型。

补充:打印一维数组可以使用静态的Arrays.toString方法,多维数组使用Arrays.deepToString方法。

5、clone 方法

Object 类中的clone方法为protected修饰的本地方法,执行的是浅拷贝,如下所示:

@IntrinsicCandidate
protected native Object clone() throws CloneNotSupportedException;

如果我们想要使用 clone 方法,需要在类上实现Cloneable接口(该接口是标记接口),并指定public修饰符。在方法内部,可以调用 Object 类的 clone 方法执行浅拷贝,也可以自己编写执行深拷贝的代码。


如有错误,欢迎指正。.... .- ...- . .- -. .. -.-. . -.. .- -.-- -.-.--

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值