首页 > 编程笔记

Java Object类用法详解

Object 是 Java 中所有类的父类,也就是说,Java 中的所有类都具备 Object 类的所有特性。因此,读者有必要掌握 Object 类的用法。

当定义一个类时,如果没有使用关键字 extends 显式指定该类继承的父类,那么编译器自动添加 extends java.lang.Object。也就是说,任何一个类在定义时如果没有明确地继承一个父类,那么它将直接继承 Object 类。因此,可以说 Java 中的每个类都是 Object 类的直接或间接子类。

Object 类中定义了所有的 Java 类经常使用的方法,子类可以直接使用或覆盖后使用。由于 Object 类中定义的方法的逻辑并不一定适用于所有子类,因此大部分子类需要重写从 Object 类继承的方法才能使用。
public class E1{
    ...
}
等价于:
public class E1 extend Object{
    ...
}
E1 类默认继承了 Object 类。

Object 类的常用方法如下表所示。

表 1 Object类的常用方法
Object类的常用方法 说明
clone() 保护方法,实现对象的浅复制,只有实现了 Cloneable 接口才可以调用该方法, 否则抛出 CloneNotSupportedException 异常
getClass() final 方法,获得运行时类型
toString() 返回该对象的字符串表现形式,常用于在调试过程中输出对象的属性值
equals() 用于判断两个对象的逻辑是否相等,如判断两个对象的各属性值是否均相等
hashCode() 为对象生成一个哈希值,用于哈希查找,在一些具有哈希功能的 Collection 中使用
finalize() 用于释放资源,因为无法确定该方法什么时候被调用,所以很少使用
wait() 使当前线程等待该对象的锁,当前线程必须是该对象的拥有者,也就是具有该对象的锁。wait() 方法直等待,直到获得锁或被中断。wait(long timeout) 设定一个超时间隔,如果在规定时间内没有获得锁就返回

下面介绍几个常用的方法。

1) public String toString():返回该对象的字符串表现形式。Object类中定义的默认逻辑是返回对象的类型+@+hashCode值,其中的 hashCode 值默认将对象的内存地址转换为整型表示。

Object 类中 toString() 方法的默认实现如下:
public String toString{
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
在实际开发中,经常需要按照对象的属性得到相应的字符串表现形式,因此,子类需要重写 toString() 方法。

另外,当使用 System.out.print() 方法打印一个对象时,如果该对象的值不为 null,那么底层调用该对象的 toString() 方法,先获取该对象的字符串表现形式,再打印该字符串。

【实例】重写toString()方法。
class Person {
    String name;
    int age;

    @Override
    public String toString() {
        return name + ",年龄:" + age;
    }
}

public class Demo {
    public static void main(String[] args) {
        Person p = new Person();
        p.age = 20;
        p.name = "张三";
        System.out.println("info:" + p.toString());

        Demo t = new Deno();
        System.out.println(t.toString()); // 这里应该调用toString方法来打印对象的字符串表示
    }
}
运行结果为:

info:张三,年龄:20
chapter8n.Example8


2) public boolean equals(Object obj):比较某个对象是否与当前对象相等。调用成员方法 equals() 并指定参数为另一个对象,用来判断这两个对象是否是相同的。

这里的“相同”有默认和自定义两种方式。
为了避免造成歧义,在开发过程中一般使用“==”运算符进行对象物理相等的判断,使用 equals() 方法进行对象逻辑相等的判断。

【实例】重写equals()方法。
import java.util.Objects;

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

    @Override
    public boolean equals(Object o) {
        // 若对象的地址一样,则认为相同
        if (this == o) return true;

        // 若参数为空,或者类型信息不一样,则认为不同
        if (o == null || getClass() != o.getClass()) return false;

        // 转换为当前类型
        Person person = (Person) o;

        // 要求基本数据类型的属性的值相等
        return age == person.age && Objects.equals(name, person.name);
    }
}
这段代码充分考虑了对象为空和类型一致等问题,但方法内容并不是唯一的。大多数 IDE 都可以自动生成 equals() 方法的代码内容。

3) hashCode()方法:返回对象的是哈希码。在一些基于 Hash Table 算法的容器中,需要根据对象的哈希码计算对象在容器中的下标。如果将一个对象存入此类容器中,那么底层会调用该对象的hashCode()方法。

Hash 算法对 hashCode() 方法的实现有如下几点要求:
与 equals() 方法类似,大多数 IDE 可以自动生成 equals() 方法的代码内容,其核心逻辑是基于对象所有参与逻辑相等比较的成员变量的值,经过特定的计算得到一个整数。在这种情况下,若两个对象参与计算的成员变量的值相等,则返回相同的哈希码;若其中一个对象的成员变量的值发生变化,则生成新的与之前不同的哈希码。

【实例】重写 hashCode() 方法。
class Person {
    String name;
    int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}
public class Demo {
    public static void main(String[] args) {
        Person p1 = new Person("小明", 15);
        Person p2 = new Person("小明", 15);
        Person p3 = new Person("小红", 13);
        System.out.println("p1.hashCode = " + p1.hashCode());
        System.out.println("p2.hashCode = " + p2.hashCode());
        System.out.println("p3.hashCode = " + p3.hashCode());
    }
}
运行结果为:

p1.hashCode = 23458769
p2.hashCode = 23458769
p3.hashCode = 23653819

推荐阅读

副业交流群 关注微信公众号,加入副业交流群,学习变现经验,交流各种打法。