【Java 学习】Java的生命之源:走进Object类的神秘花园,解密Object类的背后故事

💬 欢迎讨论:如对文章内容有疑问或见解,欢迎在评论区留言,我需要您的帮助!

👍 点赞、收藏与分享:如果这篇文章对您有所帮助,请不吝点赞、收藏或分享,谢谢您的支持!

🚀 传播技术之美:期待您将这篇文章推荐给更多对需要学习Java语言、低代码开发感兴趣的朋友,让我们共同学习、成长!

1. Object 类

1.1 为什么所有类都继承 Object 类?

在Java中,Object 类是所有类的根类。也就是说,所有的类(包括用户自定义的类)都直接或间接继承自 Object 类。这是因为在 Java 中,Object 是所有类层次结构的最顶端类。

为什么所有类都继承 Object 类?

  1. 统一的根基 :Java 为了实现统一性,决定所有类都直接或间接继承自 Object 类。这意味着每个类都可以拥有 Object 类的一些通用方法,这样使得不同类型的对象可以被处理得更加一致。

  2. 常用方法 :Object 类提供了一些常用方法,这些方法被所有类继承。比如:

    • toString():返回对象的字符串表示。
    • equals(Object obj):判断两个对象是否相等。
    • hashCode():返回对象的哈希码。
    • clone():创建并返回当前对象的副本。
    • getClass():返回对象的类信息。
    • notify(), notifyAll(), wait():用于多线程编程。

这些方法大多数类都会使用,或者根据需要进行重写,以便提供不同的行为。

  1. 多态性和泛型 :Java 中的多态性和泛型常常依赖于 Object 类。例如,在方法中接受一个 Object 类型的参数,就可以传入任何类型的对象。而且通过 Object 类的方法,可以对不同类型的对象进行统一的操作。

1.2 统一操作–举例

  1. toString() 方法
    toString() 方法是 Object 类提供的一个方法,默认返回对象的类名加上对象的哈希码的字符串表示。但是你可以在自己的类中重写这个方法,使其返回更具意义的信息。

    ```java
    class Person {
    String name;
    int age;

    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    @Override
    public String toString() {
        return "Person{name='" + name + "', age=" + age + "}";
    }
    

    }

    class Car {
    String brand;
    String model;

    Car(String brand, String model) {
        this.brand = brand;
        this.model = model;
    }
    
    @Override
    public String toString() {
        return "Car{brand='" + brand + "', model='" + model + "'}";
    }
    

    }

    public class Main {
    public static void main(String[] args) {
    Person person = new Person("John", 30);
    Car car = new Car("Toyota", "Camry");

        // 使用toString()输出对象的字符串表示
        System.out.println(person.toString()); // Person{name='John', age=30}
        System.out.println(car.toString());    // Car{brand='Toyota', model='Camry'}
    }
    

    }

    ```

  2. equals() 方法
    equals() 方法用于判断两个对象是否“相等”,默认的实现是比较对象的内存地址,但你可以重写它来根据类的字段比较对象的内容。

    ```java
    class Person {
    String name;
    int age;

    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true; // 判断是否是同一对象
        if (obj == null || getClass() != obj.getClass()) return false;
        Person person = (Person) obj;
        return age == person.age && name.equals(person.name);
    }
    

    }

    public class Main {
    public static void main(String[] args) {
    Person person1 = new Person("John", 30);
    Person person2 = new Person("John", 30);
    Person person3 = new Person("Alice", 25);

        // 使用equals()比较对象是否相等
        System.out.println(person1.equals(person2)); // true
        System.out.println(person1.equals(person3)); // false
    }
    

    }

    ```

  3. hashCode() 方法
    hashCode() 方法用于返回对象的哈希值,通常与 equals() 配合使用。如果两个对象相等,那么它们的 hashCode() 也应该相等。

    ```java
    class Person {
    String name;
    int age;

    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Person person = (Person) obj;
        return age == person.age && name.equals(person.name);
    }
    
    @Override
    public int hashCode() {
        return 31 * name.hashCode() + age;
    }
    

    }

    public class Main {
    public static void main(String[] args) {
    Person person1 = new Person("John", 30);
    Person person2 = new Person("John", 30);

        // 使用hashCode()获取对象的哈希值
        System.out.println(person1.hashCode()); // 打印哈希值
        System.out.println(person2.hashCode()); // 打印哈希值
        System.out.println(person1.equals(person2)); // true
    }
    

    }

    ```

1.3 Object 类中的所有方法

下图就是Object类,在包java.lang
在这里插入图片描述
如果把Object类中的注释全部删去,Object类的代码如下:

```java
/*
 * Copyright (c) 1994, 2022, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */

package java.lang;

import jdk.internal.misc.Blocker;
import jdk.internal.vm.annotation.IntrinsicCandidate;

public class Object {

    @IntrinsicCandidate
    public Object() {}

    @IntrinsicCandidate
    public final native Class getClass();


    @IntrinsicCandidate
    public native int hashCode();

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

    @IntrinsicCandidate
    protected native Object clone() throws CloneNotSupportedException;

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

    @IntrinsicCandidate
    public final native void notify();

    @IntrinsicCandidate
    public final native void notifyAll();


    public final void wait() throws InterruptedException {
        wait(0L);
    }

    public final void wait(long timeoutMillis) throws InterruptedException {
        long comp = Blocker.begin();
        try {
            wait0(timeoutMillis);
        } catch (InterruptedException e) {
            Thread thread = Thread.currentThread();
            if (thread.isVirtual())
                thread.getAndClearInterrupt();
            throw e;
        } finally {
            Blocker.end(comp);
        }
    }

    // final modifier so method not in vtable
    private final native void wait0(long timeoutMillis) throws InterruptedException;

    public final void wait(long timeoutMillis, int nanos) throws InterruptedException {
        if (timeoutMillis < 0) {
            throw new IllegalArgumentException("timeoutMillis value is negative");
        }

        if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException(
                    "nanosecond timeout value out of range");
        }

        if (nanos > 0 && timeoutMillis < Long.MAX_VALUE) {
            timeoutMillis++;
        }

        wait(timeoutMillis);
    }

    @Deprecated(since="9", forRemoval=true)
    protected void finalize() throws Throwable { }
}

```

我们可以从Object类中看到我们常用的toString方法、clone方法。

2. Object 类中的 clone() 方法

2.1 clone方法的定义和用途

Object 类中的 clone() 方 法用于创建当前对象的一个副本(即对象的浅拷贝)。它是一个受保护的方法(用protected修饰),所以默认情况下只有 Object 类本身及其子类可以调用。在实际开发中,clone() 方法常常被重写,以便提供更灵活的复制功能。

clone方法的声明如下:

```java
protected Object clone() throws CloneNotSupportedException;


```

说明

  • 返回值类型:Object 类型。返回的是当前对象的副本,因此返回值需要被强制转换为具体的类型。
  • 异常:CloneNotSupportedException,如果对象的类没有实现 Cloneable 接口,调用 clone() 方法时会抛出此异常。

clone() 方法是 Object 类中定义的,用于返回一个与当前对象相同的副本。在默认实现中,它是浅拷贝 ,意味着它会复制对象的基本数据类型字段,但如果对象包含引用类型的字段,那么这些字段依然指向原来的对象。

2.2 浅拷贝与深拷贝

浅拷贝(Shallow Copy) :拷贝对象时,对于基本类型的字段会进行复制,而对于引用类型的字段,会复制引用地址,也就是说,源对象和拷贝对象共享同一个引用。

解释:
在 Java 中,clone() 方法是 Object 类提供的一个原生方法。这个方法并不是直接通过构造函数来创建一个新的对象,而是通过底层的 内存复制 技术来快速创建一个与原对象相同类型的新对象。
Object 类的 clone() 方法默认会调用 native 实现,这个实现通过操作内存直接创建一个新的对象实例,并将原对象的字段内容复制到新的实例中。这意味着 clone() 方法创建的对象是一个浅拷贝,字段的值被复制,但如果字段是引用类型,那么新对象的字段仍然指向原对象的同一内存地址。

深拷贝(Deep Copy) :不仅复制对象本身,还会递归地复制对象中的所有引用类型字段,使得源对象和拷贝对象之间不再共享任何引用。

clone() 方法默认是进行浅拷贝的,如果需要实现深拷贝,则需要重写 clone() 方法并手动处理引用类型字段的复制。

2.3 总结

总结

  • clone() 是通过 Object 类的 clone() 方法实现的,底层通过内存复制技术创建新对象。
  • clone() 会复制原对象的字段值,对于基本类型字段是值复制,对于引用类型字段是引用复制。
  • clone() 返回的是一个新对象,但新对象与原对象的引用类型字段指向同一内存地址,属于浅拷贝。
  • 调用 clone() 不会触发构造函数的执行。

文章整理自互联网,只做测试使用。发布者:Lomu,转转请注明出处:https://www.it1024doc.com/5820.html

(0)
LomuLomu
上一篇 2025 年 1 月 11 日 下午5:03
下一篇 2025 年 1 月 11 日 下午6:04

相关推荐

  • Python在多个Excel文件中找出缺失数据行数多的文件

    本文介绍基于Python 语言,针对一个文件夹 下大量的Excel 表格文件,基于其中每一个文件 内、某一列数据 的特征,对其加以筛选,并将符合要求 与不符合要求 的文件分别复制到另外两个新的文件夹 中的方法。 首先,我们来明确一下本文的具体需求。现有一个文件夹,其中有大量的Excel 表格文件(在本文中我们就以csv格式的文件为例);如下图所示。 其中,每…

    2025 年 1 月 13 日
    47100
  • Claude Pro微信续费要提前几天

    Claude Pro微信续费要提前几天,围绕国内支付、代充开通、续费到账和账号验收整理。

    未分类 2026 年 5 月 30 日
    4600
  • ChatGPT Plus无需国外信用卡订阅教程

    想把 ChatGPT Plus 开到自己的账号上,最现实的问题通常是支付方式。 国内用户更希望用微信或支付宝完成购买,再把会员开通到自己的原账号。下面的方式通过卡密和 Session 确认账号,适合想保留历史记录、工作资料和日常使用习惯的人。

    未分类 4天前
    3600
  • ChatGPT Plus写作使用充值方法

    如果没有海外信用卡,ChatGPT Plus 充值会比注册账号更麻烦。 通过卡密充值,可以先用国内支付购买,再用 Session 确认当前 ChatGPT 账号。这样不需要切换共享账号,也能保留自己的使用记录和工作资料。

    未分类 1天前
    1300
  • Java【多线程】(1)进程与线程

    “`markdown 目录 1. 前言 2. 正文 2.1 什么是进程 2.2 PCB(进程控制块) 2.2.1 进程id 2.2.2 内存指针 2.2.3 文件描述符表 2.2.4 进程状态 2.2.4.1 就绪状态 2.2.4.2 阻塞状态 2.2.5 进程优先级 2.2.6 进程上下文 2.2.7 进程的记账信息 2.3 CPU操作进程的方法 2.4…

    2024 年 12 月 28 日
    70600

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信