JDK源码学习--Object类

本文深入解析Java中Object类的功能和重要性,涵盖其核心方法如toString(), getClass(), hashCode(), equals(), clone(), finalize()等的使用场景及实现原理,特别关注本地方法的作用与意义。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

摘要

大家都知道Object是所有类的父类,任何类都默认继承Object,因此省略了extends Object关键字。Objec类中的方法在任何一个java类中都可以使用,下面学习的类的顺序以jdk源码为准

Object类的常用方法:toString(),getClass(),hashCode(),equals(),clone(),finalize()
定义为final类型,不能重写的方法:getClass(),notify(),notifyAll(),wait()


1、registerNatives方法:

private static native void registerNatives();
    static {
        registerNatives();
    }

registerNatives被native修饰为本地方法,这些方法不是由java语言编写,通常由C、C++语言编写。被static修饰为静态方法。而且在静态代码块中,Object类加载的时候会先执行registerNatives方法,registerNatives方法会进行一些跟系统有关的方法调用,而这个方法的实现就在java.dll中,里面会根据不同系统来执行不同的底层操作。


2、getClass方法:

public final native Class<?> getClass();

getClass被native修饰为本地方法,被final修饰子类不能够重写此方法,返回值采用泛型,返回Object的运行时类类型,一般和getName()联合使用,如getClass().getName()。通过该方法或以获取类的元数据和方法信息。它能够获取一个类的定义信息,然后使用反射去访问类的全部信息,包括函数和字段。


3、hashCode方法:

    public native int hashCode();

hashCode被native修饰为本地方法,该方法返回该对象的哈希码值,hashCode方法在一些具有哈希功能的Collection中用到。用于哈希查找,可以减少在查找中使用equals的次数,重写了equals方法一般都要重写hashCode方法。
根据官方文档的定义,整理以下关键点:

  • hashCode的存在主要是用于查找的快捷性,如Hashtable,HashMap等,hashCode是用来在散列存储结构中确定对象的存储地址的;
  • 如果两个对象相同,就是满足于equals(Java.lang.Object) 方法,那么这两个对象的hashCode一定要相同;
  • 如果对象的equals方法被重写,那么对象的hashCode也尽量重写,并且产生hashCode使用的对象,一定要和equals方法中使用的一致,否则就会违反上面第2点;
  • 两个对象的hashCode相同,并不一定表示两个对象就相同,也就是不一定适用于equals(java.lang.Object) 方法,只能够说明这两个对象在散列存储结构中,如Hashtable,他们“存放在同一个篮子里”。
    深入理解hashcode和hash算法请移步于:https://blog.youkuaiyun.com/qq_38182963/article/details/78940047

4、equals方法:

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

equals直接判断this和obj本身的值是否相等,即用来判断调用equals的对象和形参obj所引用的对象是否是同一对象。这里的==比较的是对象的引用,也就是"地址值",如果this和obj指向的是同一块内存对象,则返回true,如果this和obj指向的不是同一块内存,则返回false。如果希望不同内存但相同内容的两个对象equals时返回true,则我们需要重写父类的equal方法,String类已经重写了object中的equals方法,比较内容是否相等。


5、clone方法:

protected native Object clone() throws CloneNotSupportedException;

clone被native修饰为本地方法,protected保护方法,实现对象的浅复制,只有实现了Cloneable接口才可以调用该方法,否则抛出CloneNotSupportedException异常。


6、toString方法:

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

toString方法返回一个字符串,类名+@+哈希值的16进制无符号整数形式。该方法用得比较多,一般子类都有覆盖。

public class Test1 {  
    public static void main(String[] args){  
        Object o1 = new Object();  
        System.out.println(o1.toString());  
    }  
} 
//输出:java.lang.Object@7852e922

7、notify方法:

public final native void notify();

notify被native修饰为本地方法,不可被重写,该方法唤醒在该对象上等待的某个线程。


8、notifyAll方法:

public final native void notifyAll();

notifyAll被native修饰为本地方法,不可被重写,该方法唤醒在该对象上等待的所有线程。


9、wait(long timeout)方法:

public final native void wait(long timeout) throws InterruptedException;

wait被native修饰为本地方法,不可被重写,调用该方法后当前线程进入睡眠状态,让当前线程等待,使线程等待指定长的时间(毫秒)。在其他线程调用了notify或是notifyAll方法或是达到指定的时长,该线程就可以被调度。其他线程调用了interrupt中断该线程,就抛出一个InterruptedException异常。


10、wait(long timeout, int nanos)方法:

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 >= 500000 || (nanos != 0 && timeout == 0)) {
            timeout++;
        }

        wait(timeout);
    }

wait不可被重写,和wait(long timeout)方法本质相同,允许更好地控制在放弃之前等待通知的时间,实时量,以毫微秒计算,计算公式如下:1000000*timeout+nanos,特别是wait(0, 0) 表示和wait(0)相同,当前线程必须拥有该对象的监视器。
三种异常:

  • IllegalArgumentException – 如果超时的值是负的或毫微秒的值不在0-999999范围内。
  • IllegalMonitorStateException – 如果当前线程不是对象监视器的拥有者。
  • InterruptedException – 如果另一个线程中断了当前线程。当这种异常被抛出当前线程的中断状态被清除。

11、wait方法:

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

实际上调用的是wait(long timeout)方法只不过timeout传的是0,只有调用了notify或是notifyAll方法,线程才会被唤醒。


12、finalize方法:

protected void finalize() throws Throwable { }

该方法是protected方法,子类可以覆盖该方法以实现资源清理工作,GC在回收对象之前调用该方法。该方法与C++中的析构函数不是对应的。C++中的析构函数调用的时机是确定的(对象离开作用域或delete掉),但Java中的finalize的调用具有不确定性。
finalize的执行周期:当对象变成(GC Roots)不可达时,GC会判断该对象是否覆盖了finalize方法,若未覆盖,则直接将其回收。否则,若对象未执行过finalize方法,将其放入F-Queue队列,由一低优先级线程执行该队列中对象的finalize方法。执行finalize方法完毕后,GC会再次判断该对象是否可达,若不可达,则进行回收,否则,对象“复活”。


JDK源码学习-String类

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值