Java 源码分析 --Object 详解

本贴最后更新于 1916 天前,其中的信息可能已经时移世异

简介

Object 类在 java.lang 包中,是所有类的父类,所有类都间接或者直接继承 Object 类。Object 类中主要有 registerNatives()、getClass()、hashCode()、equals()、clone()、toString()、notify()、notifyAll()、wait()和 finalize()等方法。其中
getClass()、notify()、notifyAll()和 wait()等方法使用 final 关键字修饰,因此子类不能覆盖。

源代码

registerNatives()方法

    private static native void registerNatives();
    //在类加载时就执行这个方法
    static {
        registerNatives();
    }

registerNatives()方法是注册一些本地方法,具体实现在本地的代码中,所以我也不清楚里面干了什么。学 Java 还是有必要学习一下 JNI 的,等我找到工作要好好研究一下。
在 Java 中,静态代码的调用顺序:父类静态--> 子类静态--> 父类非静态--> 父类构造--> 子类非静态--> 子类构造

getClass()方法

 public final native Class<?> getClass();

返回运行时的类

hashCode()方法

public native int hashCode();

返回对象的哈希码,在 HashMap 中,就是通过 hashCode 来提高查找哈希表的速度。

equals()方法

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

这里判断的是对象,对象的地址相同,返回 true,如果两个对象完全一样,但是地址不相同,也会返回 false。

在 Java 中,8 种基本数据类型变量存储的是值,可以直接使用==来比较,而引用类型数据变量需要使用 equals(),也可以重写该方法。

  • 数值型- byte(1 字节)、 short(2 字节)、int(4 字节)、 long(8 字节)、float(4 字节)、 double(8 字节)
  • 字符型- char (2 字节)
  • 布尔型-boolean (1 位)
  • 引用数据类型 —— class,interface,数组 (4 个字节)

clone()方法

实现拷贝必须实现 Cloneable 接口,并重写 clone()方法。

    protected native Object clone() throws CloneNotSupportedException;

clone 分为浅拷贝和深拷贝:

浅拷贝:拷贝出来的目标对象的指针和源对象的指针指向的内存空间是同一块空间。
深拷贝:当一个类的拷贝构造方法,不仅要复制对象的所有非引用成员变量值,还要为引用类型的成员变量创建新的实例,并且初始化为形式参数实例值。
浅拷贝
public class Professor {
    private String name;
    private int age;
    //省略get和set方法
}

public class Student implements Cloneable {
    private String name;
    private int age;
    private Professor professor;
    //省略get和set方法
    public Professor getProfessor() {
        return professor;
    }
    public void setProfessor(Professor professor) {
        this.professor = professor;
    }
    //对对象Studentclone
    @Override
    public Object clone() throws CloneNotSupportedException{
        return super.clone();
    }
}
Professor p1 = new Professor();
//省略赋值
Student s1 = new Student();
//省略赋值
Student s2 = (Student) s1.clone();
Professor p2 = s2.getProfessor();
//省略修改

在这里 s2 浅拷贝 s1,如果现在对 p2 进行修改,那么 s1 中的 Professor 也会变化。因为 p2 只是引用了 p1 的地址,对 p2 的任何操作和操作 p1 是一样的。

深拷贝

代码修改为:

public class Professor {
    private String name;
    private int age;
    //省略get和set方法
    @Override
    public Object clone() throws CloneNotSupportedException{
    	return super.clone();
    }
}

public class Student implements Cloneable {
    private String name;
    private int age;
    private Professor professor;
    //省略get和set方法
    public Professor getProfessor() {
        return professor;
    }
    public void setProfessor(Professor professor) {
        this.professor = professor;
    }
    //对对象Studentclone
    @Override
    public Object clone() throws CloneNotSupportedException{
        Student newStudent = (Student) super.clone();
        newStudent.professor = (Professor) professor.clone();
        return newStudent;
    }
}

这样就实现了深拷贝,对 p2 的任何操作都不会影响 p1。

toString()方法

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

toString()方法在子类中都会被重写,这里显示的是类名 +"@"+ 对象哈希码的十六进制数

notify()和 notifyAll()方法

    public final native void notify();
    public final native void notifyAll();

notify()方法会唤醒一个处于等待状态的线程,notifyAll()方法会唤醒同一个对象上所有调用 wait()方法的线程,优先级别高的线程先调度。

wait()方法

    //timeout是等待时间,毫秒。
    public final native void wait(long timeout) throws InterruptedException;
    //nanos是纳秒。多加一个nanos参数是为了比wait(long timeout)更好的控制时间,其中1毫秒(ms)=1000000纳秒(ns)
    public final void wait(long timeout, int nanos) throws InterruptedException {
        if (timeout < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

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

        if (nanos > 0) {
            timeout++;
        }

        wait(timeout);
    }
    //不唤醒就一直等待
    public final void wait() throws InterruptedException {
        wait(0);
    }

finalize()方法

protected void finalize() throws Throwable { }

当垃圾回收器将要回收对象所占内存之前被调用。

参考资料

Java 的 clone():深复制与浅复制

  • B3log

    B3log 是一个开源组织,名字来源于“Bulletin Board Blog”缩写,目标是将独立博客与论坛结合,形成一种新的网络社区体验,详细请看 B3log 构思。目前 B3log 已经开源了多款产品:SymSoloVditor思源笔记

    1083 引用 • 3461 回帖 • 285 关注
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3168 引用 • 8207 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...