111. Java 继承 - Object 作为超类

26 阅读4分钟

111. Java 继承 - Object 作为超类

Java 中,Object 类是所有类的根类。也就是说,每个 Java 类都是 Object 类的直接或间接子类。作为每个 Java 对象的父类,Object 类提供了若干有用的方法,供我们在实际开发中使用或覆盖。这些方法能够帮助我们操作和处理 Java 对象的基本行为。

Object 类中的常用方法

Object 类中包含了几个方法,供所有类继承和使用。以下是几个常见的方法及其功能:

  1. clone() 方法

    protected Object clone() throws CloneNotSupportedException
    

    该方法用于创建并返回当前对象的副本(克隆)。它需要调用的类实现了 Cloneable 接口,否则会抛出 CloneNotSupportedException 异常。

    示例

    class Person implements Cloneable {
        String name;
        int age;
        
        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }
        
        @Override
        protected Object clone() throws CloneNotSupportedException {
            return super.clone();
        }
    }
    
    public class TestClone {
        public static void main(String[] args) throws CloneNotSupportedException {
            Person person1 = new Person("John", 30);
            Person person2 = (Person) person1.clone();
            System.out.println(person1 == person2);  // 输出 false,表示是不同的对象
        }
    }
    
  2. equals() 方法

    public boolean equals(Object obj)
    

    默认情况下,equals() 方法通过引用比较两个对象是否相等(即是否是同一个对象)。如果要按业务需求判断两个对象的“内容”是否相等,则需要覆盖该方法。

    示例

    class Book {
        String ISBN;
        
        public Book(String ISBN) {
            this.ISBN = ISBN;
        }
        
        @Override
        public boolean equals(Object obj) {
            if (obj instanceof Book) {
                Book other = (Book) obj;
                return this.ISBN.equals(other.ISBN);
            }
            return false;
        }
    }
    
    public class TestEquals {
        public static void main(String[] args) {
            Book book1 = new Book("12345");
            Book book2 = new Book("12345");
            
            if (book1.equals(book2)) {
                System.out.println("Books are equal");
            } else {
                System.out.println("Books are not equal");
            }
        }
    }
    

    在这个例子中,我们重写了 equals() 方法来比较 Book 对象的 ISBN 是否相同。

  3. hashCode() 方法

    public int hashCode()
    

    hashCode() 方法返回对象的哈希码,哈希码是一个整数值,在使用哈希集合(如 HashMap)时非常重要。如果你重写了 equals() 方法,通常也应该重写 hashCode() 方法,以确保它们的一致性。

    示例

    @Override
    public int hashCode() {
        return ISBN.hashCode();
    }
    
  4. getClass() 方法

    public final Class<?> getClass()
    

    该方法返回表示对象的运行时类的 Class 对象。通过它,你可以获取对象的类名、超类、接口等信息。

    示例

    class Person {
        String name;
    }
    
    public class TestGetClass {
        public static void main(String[] args) {
            Person person = new Person();
            System.out.println("Class name: " + person.getClass().getSimpleName());
        }
    }
    
  5. toString() 方法

    public String toString()
    

    toString() 方法返回对象的字符串表示形式,通常用于调试。如果你没有覆盖 toString() 方法,它默认返回对象的类名和内存地址。建议在类中覆盖 toString() 方法,以便输出更具可读性的信息。

    示例

    @Override
    public String toString() {
        return "Book ISBN: " + ISBN;
    }
    

    这样调用 toString() 会输出书籍的 ISBN 信息。

  6. finalize() 方法

    protected void finalize() throws Throwable
    

    finalize() 方法由垃圾回收器在对象被销毁时调用。可以重写此方法进行清理操作(如释放资源)。然而,从 Java 9 开始,finalize() 已被弃用,强烈不建议继续使用它。对于资源释放,推荐使用 AutoCloseable 接口。

    示例

    @Override
    protected void finalize() throws Throwable {
        // 释放资源的代码
        super.finalize();
    }
    

    但是请注意,这种方法可能在某些情况下不会及时调用,因此不应依赖它来进行资源清理。

clone() 方法的细节

如果类需要支持克隆操作,它必须实现 Cloneable 接口,否则调用 clone() 时会抛出 CloneNotSupportedException 异常。clone() 方法的默认实现是浅拷贝,即它只复制对象的基本数据类型和引用对象的引用,而不复制引用对象本身。因此,如果对象中包含其他对象的引用,并且需要深拷贝(即复制引用的对象),则必须重写 clone() 方法。

示例(浅拷贝 vs 深拷贝)

class Person implements Cloneable {
    String name;
    Address address;

    public Person(String name, Address address) {
        this.name = name;
        this.address = address;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Person clonedPerson = (Person) super.clone();
        clonedPerson.address = new Address(this.address.street, this.address.city);  // 深拷贝
        return clonedPerson;
    }
}

class Address {
    String street;
    String city;

    public Address(String street, String city) {
        this.street = street;
        this.city = city;
    }
}
小结:
  1. toString():用于返回对象的字符串表示形式,调试时很有用,建议重写。
  2. equals():用于判断两个对象是否相等,需要根据实际需求重写。
  3. hashCode():如果重写了 equals(),也应重写 hashCode()
  4. clone():用于复制对象。需要实现 Cloneable 接口,默认是浅拷贝,可以根据需求实现深拷贝。
  5. finalize():用于垃圾回收时的清理操作,但已被弃用,强烈建议使用 AutoCloseable 代替。
  6. getClass():返回对象的类信息,不可重写。

这些 Object 类的方法是每个 Java 类的基础,因此理解它们及如何重写它们对于编写高质量的 Java 代码至关重要。