前言

JDK版本: 1.8

最近想看看jdk源码提高下技术深度(比较闲),万物皆对象,虽然Object大多native方法但还是很重要的。

源码

package java.lang;

/**
* Java中的始祖,万物皆Object
* @since JDK1.0
*/
public class Object { private static native void registerNatives();
static {
// 保证在clinit()最先执行,从而调native方法
registerNatives();
} /**
* 返回运行时的Class类文件,返回的是个泛型,运行时泛型会进行类型擦除,实际返回以自身为边界
* 例如 new HelloWorld().getClass()
* 返回 Class<? extends HelloWorld>
*/
public final native Class<?> getClass(); /**
* 返回一个hash code整数,主要用于集合类使用,例如HashMap
* 多次调用返回值必须一样,但是同一个应用执行了多份的时候,不保证多个执行中值相等
* 如果两个对象调equels方法返回ture,那么hash code值一定相等(所以重写equels方法一定要重写hashCode方法)
* 如果两个对象调equels方法返回false,hash code值不一定不相等,但是我们重写hashCode方法时,应该尽量做到不等,从而减少hash碰撞
* 不同虚拟机的实现不太一样,但是主要是根据对象的内存地址来计算的
*/
public native int hashCode(); /**
* 对于非空的对象进行逻辑上是否相等的比较,默认是比较的内存地址
* 再次强调哈哈,如果两个对象调equels方法返回ture,那么hash code值一定相等(所以重写equels方法一定要重写hashCode方法)
* 四大特性(1)reflexive自反性(2)symmetric对称性(3)transitive传递性(4)consistent一致性
*/
public boolean equals(Object obj) {
return (this == obj);
} /**
* 返回一个当前对象的副本,一般需要满足如下性质:
* x.clone() != x
* x.clone().getClass() == x.getClass()
* x.clone().equals(x)
* 可以根据需要实现浅拷贝和深拷贝,一般是浅拷贝
* @throws CloneNotSupportedException Object没有实现Cloneable接口,本身是不能使用clone方法的,其子类调用clone方法会抛出此异常.只有实现了Cloneable才能正常使用
* @see java.lang.Cloneable
*/
protected native Object clone() throws CloneNotSupportedException; /**
* 返回一个对象的字符串表示
* 建议所有类都重写这个方法,因为不直观
* 字符串内容,类名加上hash code转成16进制
*/
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
} /**
* 用于随机唤醒一个在对象等待池中的线程
* 被唤醒的线程不会立刻拿到对象的监视器锁,而是和其他在线程共同竞争,拿到锁之后恢复到调用wait方法时的同步状态
* 同一时间只有一个线程能拿到监视器锁
*
* @throws IllegalMonitorStateException 如果当前执行notify方法的线程没拿到对象的监视器锁
*/
public final native void notify(); /**
* 一次唤醒所有等待池中的线程,其他和notify方法一样
*/
public final native void notifyAll(); /**
* 持有对象监视器的线程可以执行awit方法把自己放入等待池中,并且放弃持有该对象的所有同步资源,不会放弃获取的其他对象的同步资源
* 有四种情况线程可以逃出等待池:
* 其他线程调用notify方法
* 其他线程调用notifyAll方法
* 其他线程调用interrupts方法
* 超时时间到了
* 逃出等待池拿到锁之后恢复到调用wait方法时的同步状态
* 特别强调,如果因为interrupts逃出了等待池,不会立刻抛出InterruptedException,需要等到线程拿到锁
* 由于偶尔会发生伪唤醒(没有调用notify或interrupts也没超时),所以我们在编码时应该如下例:
* synchronized (obj) {
* while (<condition does not hold>)
* obj.wait(timeout);
* ... // Perform action appropriate to condition
* }
* @param timeout 在等待池中的最长等待时间,时间到了就出狱了,如果值为0,则无期徒刑等待保释
* @throws IllegalArgumentException 超时时间是负数
* @throws IllegalMonitorStateException 当前线程没有拿到监视器锁
* @throws InterruptedException 中断位为true
*/
public final native void wait(long timeout) throws InterruptedException; /**
* 提供纳秒级别的等待控制,其他同wait(long timeout)
* @param nanos 额外的纳秒时间
* 0-999999.
* @throws IllegalArgumentException timeout是负数,nanos是负数或者大于999999.
*/
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);
} /**
* 和上面wait(long timeout)方法一样,只是没有超时时间
*/
public final void wait() throws InterruptedException {
wait(0);
} /**
* 当垃圾收集器判断此对象没有被任何引用,是垃圾对象了,由垃圾收集器执行此方法销毁对象,所以何时执行是不确定的
* JVM保证垃圾收集器调用此方法时候,该对象的锁不被任何线程持有了
* finalize方法只会被执行一次,所以我们可以重写此方法特定一些清除工作,或者给对象一次复活机会,但是不建议重写此方法
* @throws Throwable the {@code Exception} raised by this method
* @see java.lang.ref.WeakReference
* @see java.lang.ref.PhantomReference
*/
protected void finalize() throws Throwable { }
}

实践

clone()

public class ObjectCloneTest {

    /**
* 不实现 Cloneable 接口
*
* 输出:
* Exception in thread "main" java.lang.CloneNotSupportedException: study.ObjectCloneTest$Obj
* at java.lang.Object.clone(Native Method)
* at study.ObjectCloneTest$Obj.main(ObjectCloneTest.java:24)
*/
private static class Obj {
public static void main(String[] args) throws CloneNotSupportedException {
Obj o1 = new Obj();
Object o2 = o1.clone();
}
} /**
* 实现 Cloneable 接口,从结果看出默认实现是浅拷贝
*
* 输出:
* 两个对象地址相同么
* false
* 两个对象的属性地址相同么
* true
* 改变其中一个属性会变么?
* [1, 2]
* [1, 2]
*/
private static class ObjShallowCopy implements Cloneable { private List<String> list = new ArrayList<>(); @Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
} public static void main(String[] args) throws CloneNotSupportedException {
ObjShallowCopy o1 = new ObjShallowCopy();
o1.list.add("1");
ObjShallowCopy o2 = (ObjShallowCopy) o1.clone();
System.out.println("两个对象地址相同么");
System.out.println(o1 == o2);
System.out.println("两个对象的属性地址相同么");
System.out.println(o1.list == o2.list);
System.out.println("改变其中一个属性会变么?");
o2.list.add("2");
System.out.println(o1.list.toString());
System.out.println(o2.list.toString()); } } /**
* 实现 Cloneable 接口,比较笨拙的做了一层深拷贝,只为了演示,深拷贝也可以通过序列号等方式实现
*
* 输出:
* 两个对象地址相同么
* false
* 两个对象的属性地址相同么
* false
* 改变其中一个属性会变么?
* [1]
* [1, 2]
*/
private static class ObjDeepCopy implements Cloneable { private List<String> list = new ArrayList<>(); @Override
protected Object clone() throws CloneNotSupportedException {
ObjDeepCopy obj = (ObjDeepCopy) super.clone();
List<String> list = new ArrayList<>(obj.list.size());
list.addAll(obj.list);
obj.list = list;
return obj;
} public static void main(String[] args) throws CloneNotSupportedException {
ObjDeepCopy o1 = new ObjDeepCopy();
o1.list.add("1");
ObjDeepCopy o2 = (ObjDeepCopy) o1.clone();
System.out.println("两个对象地址相同么");
System.out.println(o1 == o2);
System.out.println("两个对象的属性地址相同么");
System.out.println(o1.list == o2.list);
System.out.println("改变其中一个属性会变么?");
o2.list.add("2");
System.out.println(o1.list.toString());
System.out.println(o2.list.toString()); } }
}

wait() 和 notify()

public class ObjectWaitNotifyTest {

    private volatile boolean flag = true;

    public static void main(String[] args) {
ObjectWaitNotifyTest obj = new ObjectWaitNotifyTest(); new Thread(() -> {
synchronized (obj) {
System.out.println("绝食!");
while (obj.flag == true) {
try {
obj.wait();
System.out.println("真香!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start(); new Thread(() -> {
synchronized (obj) {
obj.flag = false;
obj.notify();
System.out.println("海底捞走起!");
}
}).start(); /**
* 输出:
* 绝食!
* 海底捞走起!
* 真香!
*/
}
}

Java读源码之Object的更多相关文章

  1. Java读源码之ReentrantLock(2)

    前言 本文是 ReentrantLock 源码的第二篇,第一篇主要介绍了公平锁非公平锁正常的加锁解锁流程,虽然表达能力有限不知道有没有讲清楚,本着不太监的原则,本文填补下第一篇中挖的坑. Java读源 ...

  2. Java读源码之ReentrantLock

    前言 ReentrantLock 可重入锁,应该是除了 synchronized 关键字外用的最多的线程同步手段了,虽然JVM维护者疯狂优化 synchronized 使其已经拥有了很好的性能.但 R ...

  3. Java读源码之CountDownLatch

    前言 相信大家都挺熟悉 CountDownLatch 的,顾名思义就是一个栅栏,其主要作用是多线程环境下,让多个线程在栅栏门口等待,所有线程到齐后,栅栏打开程序继续执行. 案例 用一个最简单的案例引出 ...

  4. Java读源码之Thread

    前言 JDK版本:1.8 阅读了Object的源码,wait和notify方法与线程联系紧密,而且多线程已经是必备知识,那保持习惯,就从多线程的源头Thread类开始读起吧.由于该类比较长,只读重要部 ...

  5. Java读源码之ThreadLocal

    前言 JDK版本: 1.8 之前在看Thread源码时候看到这么一个属性 ThreadLocal.ThreadLocalMap threadLocals = null; ThreadLocal实现的是 ...

  6. Java读源码之LockSupport

    前言 JDK版本: 1.8 作用 LockSupport类主要提供了park和unpark两个native方法,用于阻塞和唤醒线程.注释中有这么一段: 这个类是为拥有更高级别抽象的并发类服务的,开发中 ...

  7. java读源码 之 map源码分析(HashMap,图解)一

    ​ 开篇之前,先说几句题外话,写博客也一年多了,一直没找到一种好的输出方式,博客质量其实也不高,很多时候都是赶着写出来的,最近也思考了很多,以后的博客也会更注重质量,同时也尽量写的不那么生硬,能让大家 ...

  8. java读源码 之 queue源码分析(PriorityQueue,附图)

    今天要介绍的是基础容器类(为了与并发容器类区分开来而命名的名字)中的另一个成员--PriorityQueue,它的大名叫做优先级队列,想必即使没有用过也该有所耳闻吧,什么?没..没听过?emmm... ...

  9. java读源码 之 list源码分析(ArrayList)---JDK1.8

    java基础 之 list源码分析(ArrayList) ArrayList: 继承关系分析: public class ArrayList<E> extends AbstractList ...

随机推荐

  1. codeforces 762 D. Maximum path(dp)

    题目链接:http://codeforces.com/problemset/problem/762/D 题意:给出一个3*n的矩阵然后问从左上角到右下角最大权值是多少,而且每一个点可以走上下左右,但是 ...

  2. POJ 1390 Blocks (区间DP) 题解

    题意 t组数据,每组数据有n个方块,给出它们的颜色,每次消去的得分为相同颜色块个数的平方(要求连续),求最大得分. 首先看到这题我们发现我们要把大块尽可能放在一起才会有最大收益,我们要将相同颜色块合在 ...

  3. Altera Quartus II 15.0安装

       写在前面的话 开始学习之前,我们首先应该选择并安装好自己的开发工具,那么我们用什么软件来编译代码呢?梦翼师兄推荐给大家的是Altera 目前最新的Quartus II 15.0 版本,当然啦,这 ...

  4. Storm 系列(三)—— Storm 单机版本环境搭建

    1. 安装环境要求 you need to install Storm's dependencies on Nimbus and the worker machines. These are: Jav ...

  5. 4.Sentinel源码分析— Sentinel是如何做到降级的?

    各位中秋节快乐啊,我觉得在这个月圆之夜有必要写一篇源码解析,以表示我内心的高兴~ Sentinel源码解析系列: 1.Sentinel源码分析-FlowRuleManager加载规则做了什么? 2. ...

  6. java多线程之Executor框架

    Executor框架简介 Executor框架的结构 Executor框架主要由3大部分组成: 任务: 包括被执行的任务需要实现的接口:Runable 接口.Callable接口: 任务的执行: 包括 ...

  7. Mybatis源码阅读-配置文件及映射文件解析

    Mybatis源码分析: 1.配置文件解析: 1.1源码阅读入口: org.apache.ibatis.builder.xml.XMLConfigBuilder.parse(); 功能:解析全局配置文 ...

  8. FreeSql (三十一)分区分表

    分区 分区就是把一个数据表的文件和索引分散存储在不同的物理文件中.把一张表的数据分成N多个区块,这些区块可以在同一个磁盘上,也可以在不同的磁盘上,数据库不同实现方式有所不同. 与分表不同,一张大表进行 ...

  9. 手把手教程: CentOS 6.5 LVS + KeepAlived 搭建 负载均衡 高可用 集群

    为了实现服务的高可用和可扩展,在网上找了几天的资料,现在终于配置完毕,现将心得公布处理,希望对和我一样刚入门的菜鸟能有一些帮助. 一.理论知识(原理) 我们不仅要知其然,而且要知其所以然,所以先给大家 ...

  10. SSO-CAS实现单点登录服务端

    目录 CAS-SSO 一.单点登录-CAS 二.下载搭建CAS 1. 下载 CAS 5.3 2. 导入IDEA 3. 打包war 3. war包部署到Tomcat 4. 启动Tomcat,访问 htt ...