小熊奶糖(BearCandy)
小熊奶糖(BearCandy)
发布于 2025-10-11 / 0 阅读
0
0

Java中所有类的根父类——`Object`

Java中所有类的根父类——Object

1. Object类概述

java.lang.Object 类是Java类层次结构中的根类。每个类都使用 Object 作为超类(父类)。所有对象(包括数组)都实现了这个类的方法。

这意味着,在Java中,你可以用 Object 类型的变量来引用任何类型的对象。这就是Java实现多态性的基石之一。

// 可以用Object引用指向任何对象
Object obj1 = new String("Hello");
Object obj2 = new Integer(100);
Object obj3 = new MyCustomClass();
Object obj4 = new int[]{1, 2, 3}; // 数组也是对象

2. 常用方法详解

Object类提供了多个核心方法,其中一些经常需要被子类重写以实现特定的逻辑。

2.1 toString()

  • 作用:返回该对象的字符串表示。
  • 默认实现:返回 类名@哈希码的无符号十六进制表示(例如 java.lang.Object@1b6d3586)。
  • 为什么要重写:默认的返回值对于调试和日志记录来说不直观。重写此方法可以返回一个能简洁地表达对象内容、易于阅读的字符串。
  • 约定:建议为所有子类重写此方法,返回一个“简洁但信息丰富、易于阅读”的字符串。
// 未重写toString
public class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public static void main(String[] args) {
        Person person = new Person("Alice", 25);
        System.out.println(person); // 输出:com.example.Person@1b6d3586
    }
}

// 重写toString后
public class Person {
    private String name;
    private int age;

    // ... 构造方法等

    @Override
    public String toString() {
        // 返回一个描述对象内容的字符串
        return "Person{name='" + name + "', age=" + age + '}';
    }

    public static void main(String[] args) {
        Person person = new Person("Alice", 25);
        System.out.println(person); // 输出:Person{name='Alice', age=25}
        // 当对象被用在字符串连接中时,也会自动调用其toString()方法
        String info = "Person Info: " + person;
        System.out.println(info); // 输出:Person Info: Person{name='Alice', age=25}
    }
}

2.2 equals(Object obj)

  • 作用:指示其他某个对象是否与此对象“相等”。
  • 默认实现:比较两个对象的内存地址是否相同(即 == 的比较)。
  • 为什么要重写:当我们希望根据对象的内容(即字段的值)来判断逻辑上的相等,而不是根据内存地址时,就需要重写此方法。
  • 重写约定(必须遵循的规则):
    1. 自反性x.equals(x) 必须返回 true
    2. 对称性:如果 x.equals(y)true,那么 y.equals(x) 也必须为 true
    3. 传递性:如果 x.equals(y)true,且 y.equals(z)true,那么 x.equals(z) 也必须为 true
    4. 一致性:只要对象内容没变,多次调用 x.equals(y) 应该始终返回相同的结果。
    5. 对于任何非 null 的引用值 xx.equals(null) 必须返回 false
public class Person {
    private String name;
    private int age;

    // ... 构造方法、toString等

    @Override
    public boolean equals(Object obj) {
        // 1. 检查是否是同一个对象的引用
        if (this == obj) return true;
        // 2. 检查传入对象是否为null,或者是否是同一个类
        if (obj == null || this.getClass() != obj.getClass()) return false;
        // 3. 将obj向下转型为Person
        Person person = (Person) obj;
        // 4. 比较关键字段的值
        // 使用Objects.equals来处理可能为null的name字段
        return age == person.age && Objects.equals(name, person.name);
    }
}

2.3 hashCode()

  • 作用:返回对象的哈希码值。主要用于哈希表(如 HashMap, HashSet, Hashtable)中。
  • equals() 的关系非常重要):
    • 如果两个对象根据 equals() 方法是相等的,那么对这两个对象中的每个对象调用 hashCode 方法都必须生成相同的整数结果。
    • 如果两个对象根据 equals() 方法是不相等的,不要求它们的 hashCode 值也必须不同。但是,为不相等的对象生成不同的哈希码可以提高哈希表的性能。
  • 为什么要重写当你重写了 equals() 方法,就必须重写 hashCode() 方法,以遵守上述约定。否则,你的对象在放入哈希集合时会出现不可预知的行为。
public class Person {
    private String name;
    private int age;

    // ... 构造方法、toString、equals等

    @Override
    public int hashCode() {
        // 使用Objects.hash()工具方法,可以方便地计算多个字段的哈希值
        return Objects.hash(name, age);
    }
}

2.4 getClass()

  • 作用:返回此 Object 的运行时类(即实际类型)。
  • 特点:这是一个 final 方法,不能被重写。它返回一个 Class 对象,可以通过该对象获取类的元信息(如类名、方法、字段等),是Java反射机制的入口。
Person person = new Person("Bob", 30);
Class<?> clazz = person.getClass();
System.out.println(clazz.getName()); // 输出:com.example.Person
System.out.println(clazz.getSimpleName()); // 输出:Person

2.5 clone()

  • 作用:创建并返回此对象的一个副本。
  • 注意点
    1. 要使用 clone(),类必须实现 Cloneable 标记接口,否则会抛出 CloneNotSupportedException
    2. 默认的 clone() 方法是“浅拷贝”。如果对象包含引用类型的字段,拷贝对象和原对象将共享这些引用字段。如果需要“深拷贝”,必须在重写 clone() 方法时手动处理。
public class Person implements Cloneable {
    private String name;
    private int age;

    // ... 其他方法

    @Override
    public Object clone() throws CloneNotSupportedException {
        // 先调用super.clone()进行浅拷贝
        Person cloned = (Person) super.clone();
        // 如果需要深拷贝,在这里对引用类型字段进行克隆
        // cloned.someReference = (SomeClass) this.someReference.clone();
        return cloned;
    }
}

2.6 finalize()

  • 作用:当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。用于在对象被回收前执行清理操作。
  • 重要提示此方法已过时(Deprecated),从Java 9开始标记为废弃。它的执行时机不确定,甚至不保证会被调用。依赖 finalize() 进行资源清理是非常危险的,容易导致内存泄漏和性能问题。应该使用 try-with-resources 或显式调用 close() 方法来管理资源。

3. 其他方法

  • wait(), notify(), notifyAll():这些方法与线程间的通信(等待/通知机制)相关。它们都是 final 方法,不能被重写。必须在同步代码块(synchronized block)或同步方法中使用。

4. 总结

方法 作用 是否需要重写 关键点
toString() 返回对象字符串表示 强烈建议 便于阅读和调试
equals(Object) 判断对象内容是否相等 需要时重写 比较内容而非地址
hashCode() 返回哈希码 重写equals时必须重写 遵守与equals的约定
getClass() 获取运行时类 不能重写 反射基础
clone() 创建对象副本 需要时重写 需实现 Cloneable,注意深浅拷贝
finalize() 垃圾回收前清理 不应使用 已废弃,不可靠

理解并正确使用 Object 类的方法,是编写高质量、健壮的Java代码的基础。特别是 equals()hashCode() 的配合使用,是面试和实际开发中的常见考点。


评论