JDK源码阅读-基础类-Object

3 篇文章 0 订阅

一、Object.class了解

1、该类处于java.lang这个package中;
2、类中包含如下method:
在这里插入图片描述 3、native方法的注册 在这里插入图片描述a、native修饰的方法是java中的原生方法,有c/c++ 实现
b、静态代码块在类加载的时候被执行
c、类加载的时候执行原生方法registerNatives,该方法实现java中声明的native方法与c/c++函数之间的绑定,即native方法的注册
d、Object中的native方法:在这里插入图片描述

二、Method分解

2.1 getClass()

getClass

  • 此method被final修饰,不可被继承;因Object是所有类的基类,故所有实例在调用getClass()方法是都是调用的Object的getClass()方法,返回调用实例的Class类;
  • 此method被final修饰原因分析:
    • getClass()方法的目的是返回调用实例所属的Class类(Object运行时实例类型)
    • Object类是所以类的基类,即Object会有很多派生类;
    • 如果getClass()方法可以被继承并被重写的话,实例a在调用getClass()时返回的可能是另外一个实例b的Class类B,而不是a实例所属的A类,原因是B类中重写的getClass(),A类中没有重写getClass();
    • 综上,final修饰getClass()是为了保证获取结果的准确性
  • getClass更多应用场景是JAVA的反射机制;

参考资料:

2.2 hashCode() && equals()

在这里插入图片描述

  • 2个method都没有被final修饰,可以被子类继承和重写;
  • hashCode()被native修饰,属于底层原生方法;默认是有对象的地址转换而来(根据不同的对象转换成不同的hash值);
  • 默认的hashCode(0返回值常常不是我们想要的hash值,所以hashCode()经常需要重写;
  • hashCode()重写时的3个约定:
    • 在java程序执行过程中,在一个对象没有被改变的情况下,无论对象被调用多少次,返回的都是相同的int值;这个int值在不同的程序中可以不同;
    • 如果2个对象通过equals()对比相等的话,那么hashCode()返回值也必定相等;
    • 如果2个对象equals()返回值不相等,其hashCode()返回值可以不相等;(不相等的对象如果hashCode()也不相等的话,可以提高程序效率)
    • 相同的类,在不同的程序中,hashCode()可能返回不同的值;
    • hashCode()返回对象的hash值;
    • hashCode方法常用于散列集合框架,如HashTable、HashMap、HashSet

参考资料:

2.3 equals()

在这里插入图片描述

  • Object的equals()默认比较的是2个对象的地址,即是否为同一个内存对象;
  • 重写equals()的时候必须重写hashCode();此约定是为了实现***如果2个对象通过equals()对比相等的话,那么hashCode()返回值也必定相等***这个要求
  • equals默认5个需要遵守的原则: 在这里插入图片描述
    参考资料:Object对象你真理解了吗?
2.4 clone()

在这里插入图片描述

  • clone()创建并返回实例对象的拷贝对象;
  • 新拷贝的对象和元实例对象一般不相等,即在不同的内存地址中(拷贝的对象与原有实例对象是相互独立的:浅拷贝不一定完全独立,可能存在成员变量与原有实例对象共用);
  • 新拷贝的对象和原实例对象的字节码文件可能相同,可能不同(浅拷贝,存在未被拷贝的成员变量);
  • Object没有实现Cloneable接口,在Object上调用clone()会抛异常CloneNotSupportedException;
  • 深拷贝指的是该对象的成员变量(如果是可变引用)都应该克隆一份,浅拷贝指的是成员变量没有被克隆一份;
  • 如何克隆对象:
    • 克隆的对象要实现Cloneable接口
    • 重写clone方法,最好修饰成public
      在这里插入图片描述
      在这里插入图片描述
  • Java:由Object.clone()而引出的protected权限问题

参考资料:

2.5 toString()

在这里插入图片描述

  • 默认返回调用实例所属类名 + @ + 调用实例hash地址的16进制无符号整数字符串;
  • 主要用来表示调用实例对象情况,默认返回值通常达不到所需要求,常常需要重写该方法;
2.6 notify() && notifyAll()

在这里插入图片描述

  • 不可被重写的java原生方法;可以被继承;
  • notify()随机唤醒正在等待的其中一个对象;(可能存在多个对象都在等待)。notifyAll()唤醒正在等待的所有对象;
  • 只能有监听器对象的所有者来调用;(都是在同步代码块中被调用)
  • 一次只能有一个线程获取监听器对象;
  • 3中成为监听器对象所有者的方式:
    • 调用该实例的同步方法;
    • 执行该实例对象的同步代码块;
    • 执行该对象对应的静态代码块;
2.7 wait() && wait(long timeout) && wait(long timeout, int nanos)

在这里插入图片描述

  • 使当前线程处于等待状态,直到调用唤醒方法或等待时间已过;
  • 线程等待会释放其持有的对象锁;(只会解锁当前调用wait()的对象)
  • 只能由监听器对象来调用;(都是在同步代码块中被调用)
  • 当线程离开等待状态后,会进入就绪状态;
  • 线程离开等待状态的方式:
    • 调用唤醒方法;
    • 线程中断;(此时会抛出异常) 在这里插入图片描述
    • 等待时间已过;
    • 虚假唤醒;(一般使用循环+条件控制来避免虚假唤醒的发生)
      在这里插入图片描述
  • 等待时间以毫秒计算,最低等待时间是0;附加时间以纳秒为计算,一般附加1毫秒;
2.8 wait() 与 notify()
  • 无论是wait、notify还是notifyAll()都需要由监听器对象(锁对象)来进行调用;简单来说:他们都是在同步代码块中调用的,否则会抛出异常!
  • wait()和 notify()是Java给我们提供线程之间通信的API;
  • 在Object类上定义而不在Thread类上定义的原有分析:
    • 因为我们的锁是对象锁,每个对象都可以成为锁。
    • 让当前线程等待某个对象的锁,当然应该通过这个对象来操作了。
    • 锁对象是任意的,所以这些方法必须定义在Object类中
  • notify方法调用后,被唤醒的线程不会立马获得到锁对象。而是等待notify的synchronized代码块执行完之后才会获得锁对象
  • sleep和wait有什么区别:
    在这里插入图片描述

参考资料:Java锁机制了解一下

2.9 finalize()

在这里插入图片描述

  • java的内存管理依赖于JVM实现的GC(Garbage Collection)机制来实现内存的回收, GC相关的内容后面再展开;

  • JVM在进行GC时, 如果这个对象需要被回收, 会先判断该方法是否有被重写, 若未重写, 则直接回收该对象内存空间;

  • 反之则判断该对象的finalize是否被执行过, 如果没有执行过, 会先放入一个队列中, 由低优先级的线程去执行该对象的finalize方法, 执行完毕后再判断该对象是否需要回收;

  • 如果该对象已经执行过一遍finalize方法了, 直接回收对象的内存空间;
    在这里插入图片描述

    参考资料:java基础之Object类解析(二)

三、参考资料

1、JDK源码阅读之Object类

2、Object对象你真理解了吗?

3、Java:由Object.clone()而引出的protected权限问题

4、java基础之Object类解析(一)

5、java基础之Object类解析(二)

6、Java锁机制了解一下

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值