第一章节,不能再往前了!java
前言:缓存
学习jdk源码,提升本身的code能力ide
源码学习的过程是经过,对自身的提高远比贴吧来的更准确,更实用。源码分析
注:所有代码会在帖子最后面贴出学习
开山第一斧:Object.classui
学习思路,熟悉方法的使用和实现原理this
@Test public void testGetClass() { User user = new User(); Class<? extends User> userClass = user.getClass(); System.out.println(userClass.getName()); System.out.println(userClass.getSimpleName()); System.out.println(userClass.getTypeName()); /** * ....能够获取更多信息 * 执行结果 * com.daly.demo.test.TestObject$User * User * com.daly.demo.test.TestObject$User */ }
@Test public void testHashCode() { User user1 = new User(1, "jack"); User user2 = new User(1, "jack"); HashSet<User> set = new HashSet<>(); set.add(user1); set.add(user2); System.out.println("user1.hashcode =" + user1.hashCode()); System.out.println("user2.hashcode =" + user2.hashCode()); System.out.println("uesr1.equals(user2) is " + user1.equals(user2)); System.out.println("set.size = " + set.size()); /** * 在使用HashMap,HashSet时,经过比较hahscode的值来判断是否相等 * 运行结果 * user1.hashcode =1023487453 * user2.hashcode =1865127310 * uesr1.equals(user2) is false * set.size = 2 */ }
仅重写了equals方法,再使用set时,没法判断重复对象,由于,他们的hashcode值不同,被认为是不一样的key,spa
@Test public void testHashCodeOverride() { UserOverride user1 = new UserOverride(1, "jack"); UserOverride user2 = new UserOverride(1, "jack"); HashSet<UserOverride> set = new HashSet<>(); set.add(user1); set.add(user2); System.out.println("user1.hashcode =" + user1.hashCode()); System.out.println("user2.hashcode =" + user2.hashCode()); System.out.println("uesr1.equals(user2) is " + user1.equals(user2)); System.out.println("set.size =" + set.size()); /** * 在使用HashMap,HashSet时,经过比较hahscode的值来判断是否相等 * 运行结果 * user1.hashcode =1023487453 * user2.hashcode =1865127310 * uesr1.equals(user2) is true * set.size =2 */ }
同时重写equals和hashcode方法,代码以下:.net
@Test public void testHashCodeOverride() { UserOverride user1 = new UserOverride(1, "jack"); UserOverride user2 = new UserOverride(1, "jack"); HashSet<UserOverride> set = new HashSet<>(); set.add(user1); set.add(user2); System.out.println("user1.hashcode =" + user1.hashCode()); System.out.println("user2.hashcode =" + user2.hashCode()); System.out.println("uesr1.equals(user2) is " + user1.equals(user2)); System.out.println("set.size =" + set.size()); /** * 在使用HashMap,HashSet时,经过比较hahscode的值来判断是否相等 * 运行结果 * user1.hashcode =3254238 * user2.hashcode =3254238 * uesr1.equals(user2) is true * set.size =1 */ }
//jdk源码的equals方法实现,是比较内存的地址,在比较继承 //在比较对象是否相等,须要重写这个方法,并且还要重写hashcode方法,缘由是set在判断对象是否已存在时,是经过对象的hashcode来判断的 public boolean equals(Object obj) { return (this == obj); }
@Test public void testEquals() { int i1 = 127,i2 = 127; Integer ibox1 = 128, ibox2 = 128; System.out.println("int i1 = 127,i2 = 127; --> i1 == i2 is " + (i1 == i2)); System.out.println("Integer ibox1 = 128, ibox2 = 128; --> ibox1 == ibox2 is " + (ibox1 == ibox2)); System.out.println("Integer ibox1 = 128, ibox2 = 128; --> ibox1.equals(ibox2) is " + ibox1.equals(ibox2)); /** * 由于Integer在重写equals方法时, * 执行结果 * int i1 = 127,i2 = 127; --> i1 == i2 is true * Integer ibox1 = 128, ibox2 = 128; --> ibox1 == ibox2 is false * Integer ibox1 = 128, ibox2 = 128; --> ibox1.equals(ibox2) is true */ }
//jdk8 源码部分 //在进行自动拆装箱时,编译器会使用Integer.valueof()来建立Integer实例。 //代码解释,先从缓存拿,没有拿到就建立一个Integer返回,Integer的取值范围在-128~127全部超过127时,就会出现陷阱了 public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }
@Test public void testCloneShallow() throws CloneNotSupportedException { Role role = new Role(1, "normal"); User user = new User(1, "jack"); user.setRole(role); User userClone; userClone = (User) user.clone(); System.out.println("user.equals(userClone) is " + user.equals(userClone)); System.out.println("user == userClone is " + (user == userClone)); System.out.println( "user.getRole() == userClone.getRole() is " + (user.getRole() == userClone.getRole())); System.out.println("------------ 分割线 -----------"); user.getRole().setRoleName(user.getRole().getRoleName().toUpperCase()); System.out.println("user.getRole().getRoleName() is "+user.getRole().getRoleName()); System.out.println("userClone.getRole().getRoleName() is "+userClone.getRole().getRoleName()); /** * 此处的user.clone()为浅拷贝,因此user和userClone的UserOverride是指向同一内存地址的对象 * 执行结果 * 由于User没有重写equals方法,因此 equals的结果跟== 都为false * user.equals(userClone) is false * user == userClone is false * user.getRole() == userClone.getRole() is true * ------------ 分割线 ----------- * user.getRole().getRoleName() is NORMAL * userClone.getRole().getRoleName() is NORMAL */ }
@Test public void testCloneDeep() throws CloneNotSupportedException { RoleOverride role = new RoleOverride(1, "normal"); UserOverride user = new UserOverride(1, "jack"); user.setRoleOverride(role); UserOverride userClone; userClone = (UserOverride) user.clone(); System.out.println("user.equals(userClone) is " + user.equals(userClone)); System.out.println("user == userClone is " + (user == userClone)); System.out.println("they'er getUserOverride is " + (user.getRoleOverride() == userClone.getRoleOverride())); System.out.println("------------ 分割线 -----------"); user.getRoleOverride().setRoleName(user.getRoleOverride().getRoleName().toUpperCase()); System.out.println("user.getRole().getRoleName() is "+user.getRoleOverride().getRoleName()); System.out.println("userClone.getRole().getRoleName() is "+userClone.getRoleOverride().getRoleName()); /** * 此处的user.clone()为浅拷贝,因此user和userClone的UserOverride是指向同一内存地址的对象 * 执行结果 * 由于 RoleOverride 重写了equals方法,因此 equals的结果为true, == 结果为 false * user.equals(userClone) is true * user == userClone is false * they'er getUserOverride is false * ------------ 分割线 ----------- * user.getRole().getRoleName() is NORMAL * userClone.getRole().getRoleName() is normal */ }
深度clone的关键代码以下:线程
@Override protected Object clone() throws CloneNotSupportedException { Object clone = super.clone(); RoleOverride roleOverride = ((UserOverride)clone).getRoleOverride(); ((UserOverride)clone).setRoleOverride((RoleOverride) roleOverride.clone()); return clone; }
jdk8 的Object的toString方法的源码以下
//返回的是className@哈希值 //在建立类时,须要重写这个方法 public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); }
notify唤醒了其中一个等待的线程,
/** * 来自博客 https://blog.csdn.net/u014658905/article/details/81035870 */ @Test public void testNotify() throws InterruptedException { final NotificationTest test = new NotificationTest(); Runnable waitTask = () -> { try { test.shouldGo(); } catch (InterruptedException ex) { System.out.println(ex.getMessage()); } System.out.println(Thread.currentThread().getName() + " finished Execution"); }; Runnable notifyTask = () -> { test.go2(); System.out.println(Thread.currentThread().getName() + " finished Execution"); }; Thread t1 = new Thread(waitTask, "WT1"); //will wait Thread t2 = new Thread(waitTask, "WT2"); //will wait Thread t3 = new Thread(waitTask, "WT3"); //will wait Thread t4 = new Thread(notifyTask, "NT1"); //will notify //starting all waiting thread t1.start(); t2.start(); t3.start(); //pause to ensure all waiting thread started successfully sleep(200); //starting notifying thread t4.start(); /** * 运行结果 * WT1 is going to wait on this object * WT2 is going to wait on this object * WT3 is going to wait on this object * NT1 is going to notify all or one thread waiting on this object * NT1 finished Execution * WT1 is woken up * WT1 finished Execution */ }
notifyAll唤醒了所有等待的线程
/** * 来自博客 https://blog.csdn.net/u014658905/article/details/81035870 */ @Test public void testNotifyAll() throws InterruptedException { final NotificationTest test = new NotificationTest(); Runnable waitTask = () -> { try { test.shouldGo(); } catch (InterruptedException ex) { System.out.println(ex.getMessage()); } System.out.println(Thread.currentThread().getName() + " finished Execution"); }; Runnable notifyTask = () -> { test.go(); System.out.println(Thread.currentThread().getName() + " finished Execution"); }; Thread t1 = new Thread(waitTask, "WT1"); //will wait Thread t2 = new Thread(waitTask, "WT2"); //will wait Thread t3 = new Thread(waitTask, "WT3"); //will wait Thread t4 = new Thread(notifyTask, "NT1"); //will notify //starting all waiting thread t1.start(); t2.start(); t3.start(); //pause to ensure all waiting thread started successfully sleep(200); //starting notifying thread t4.start(); /** * 运行结果 * WT1 is going to wait on this object * WT2 is going to wait on this object * WT3 is going to wait on this object * NT1 is going to notify all or one thread waiting on this object * NT1 finished Execution * WT3 is woken up * WT3 finished Execution * WT2 is woken up * WT2 is going to wait on this object * WT1 is woken up * WT1 is going to wait on this object */ }
/** * 除了耗时完成后自动唤醒,还能够被notify和notifyAll唤醒 * notify和notifyAll唤醒方式,如上面的例子所示 * @throws InterruptedException */ @Test public void testWait() throws InterruptedException { Runnable myThread = () -> { synchronized (this) { try { System.out.println("myThread start at "+ new SimpleDateFormat("mm:ss").format(new Date())); //wait(5000);//5秒钟以后唤醒当前线程.继续执行 wait();//一直等待 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("myThread run end"); } }; Thread t1 = new Thread(myThread, "t1"); //will wait synchronized (t1) { t1.start(); t1.wait(2000); //2秒钟以后,唤醒了main线程继续执行 //t1.wait(2000,1000);//1000000*2000+1000 毫微秒钟以后,唤醒了main线程,彻底体现不出来这第二个参数的意义 //t1.wait();//mian线程一直等待,没有被其余线程唤醒 System.out.println("mainThread wake up at "+ new SimpleDateFormat("mm:ss").format(new Date())); System.out.println("main run end"); } /** * 运行结果以下 * 当myThread被提早唤醒时,后面的代码不会被执行 * myThread start at 38:57 * myThread run end * mainThread wake up at 39:02 * main run end * 或 *myThread start at 41:52 * mainThread wake up at 41:54 * main run end */ }
最后一个方法就是finalize
/** * 很经典的GC回收机制实例 */ @Test public void testFinalize() throws InterruptedException { // 新建对象,由于SAVE_HOOK指向这个对象,对象此时的状态是(reachable,unfinalized) GC.SAVE_HOOK = new GC(); //将SAVE_HOOK设置成null,此时刚才建立的对象就不可达了,由于没有句柄再指向它了,对象此时状态是(unreachable,unfinalized) GC.SAVE_HOOK = null; //强制系统执行垃圾回收,系统发现刚才建立的对象处于unreachable状态,并检测到这个对象的类覆盖了finalize方法,所以把这个对象放入F-Queue队列,由低优先级线程执行它的finalize方法,此时对象的状态变成(unreachable, finalizable)或者是(finalizer-reachable,finalizable) System.gc(); // sleep,目的是给低优先级线程从F-Queue队列取出对象并执行其finalize方法提供机会。在执行完对象的finalize方法中的super.finalize()时,对象的状态变成(unreachable,finalized)状态,但接下来在finalize方法中又执行了SAVE_HOOK = this;这句话,又有句柄指向这个对象了,对象又可达了。所以对象的状态又变成了(reachable, finalized)状态。 Thread.sleep(500); // 这里楼主说对象处于(reachable,finalized)状态应该是合理的。对象的finalized方法被执行了,所以是finalized状态。又由于在finalize方法是执行了SAVE_HOOK=this这句话,原本是unreachable的对象,又变成reachable了。 if (null != GC.SAVE_HOOK) { //此时对象应该处于(reachable, finalized)状态 // 这句话会输出,注意对象由unreachable,通过finalize复活了。 System.out.println("Yes , I am still alive"); } else { System.out.println("No , I am dead"); } // 再一次将SAVE_HOOK放空,此时刚才复活的对象,状态变成(unreachable,finalized) GC.SAVE_HOOK = null; // 再一次强制系统回收垃圾,此时系统发现对象不可达,虽然覆盖了finalize方法,但已经执行过了,所以直接回收。 System.gc(); // 为系统回收垃圾提供机会 Thread.sleep(500); if (null != GC.SAVE_HOOK) { // 这句话不会输出,由于对象已经完全消失了。 System.out.println("Yes , I am still alive"); } else { System.out.println("No , I am dead"); } }
Object.class的全部方法都举了栗子,欢迎你们指正。
补充: 比较obj.hashcode 和 System.identityHashCode(obj) 的区别
/** * 比较obj.hashCode 和系统的 System.identityHashCode(obj)的不一样 * obj.hashCode比较的是值,是obj重写的hashCode方法, * System.identityHashCode是将obj的存储位置转换成为hashCode */ @Test public void testSystemHashCode() throws CloneNotSupportedException { User u1 = new User(1,"jack"); User u2 = new User(1,"jack"); Role role = new Role(1,"normal"); u1.setRole(role); u2.setRole(role); User u1Clone = (User) u1.clone();//此处为浅拷贝,user.getRole指向的是同一个内存地址 System.out.println("System.identityHashCode(u1)=="+System.identityHashCode(u1.getRole())); System.out.println("System.identityHashCode(u1Clone)=="+System.identityHashCode(u1Clone.getRole())); System.out.println("System.identityHashCode(u2)=="+System.identityHashCode(u2.getRole())); System.out.println("--------------- 分割线 --------------"); UserOverride u3 = new UserOverride(1, "jack"); UserOverride u4 = new UserOverride(1, "jack"); RoleOverride r1 = new RoleOverride(1,"normal"); u3.setRoleOverride(r1); u4.setRoleOverride(r1); //此处是深克隆,u3.getRoleOverride是指向不一样的物理地址 UserOverride u3Clone = (UserOverride) u3.clone(); System.out.println("System.identityHashCode(u3)=="+System.identityHashCode(u3.getRoleOverride())); System.out.println("System.identityHashCode(u3Clone)=="+System.identityHashCode(u3Clone.getRoleOverride())); System.out.println("System.identityHashCode(u4)=="+System.identityHashCode(u4.getRoleOverride())); /** * 运行结果 * System.identityHashCode(u1)==1023487453 * System.identityHashCode(u1Clone)==1023487453 * System.identityHashCode(u2)==1023487453 * --------------- 分割线 -------------- * System.identityHashCode(u3)==1865127310 * System.identityHashCode(u3Clone)==515132998 * System.identityHashCode(u4)==1865127310 */ }
下面是所有源码,写的都是内部类+@Test注解,能够直接运行
import static java.lang.Thread.sleep; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashSet; import org.junit.Test; public class TestObject { @Test public void testGetClass() { User user = new User(); Class<? extends User> userClass = user.getClass(); System.out.println(userClass.getName()); System.out.println(userClass.getSimpleName()); System.out.println(userClass.getTypeName()); /** * ....能够获取更多信息 * 执行结果 * com.daly.demo.test.TestObject$User * User * com.daly.demo.test.TestObject$User */ } @Test public void testHashCode() { User user1 = new User(1, "jack"); User user2 = new User(1, "jack"); HashSet<User> set = new HashSet<>(); set.add(user1); set.add(user2); System.out.println("user1.hashcode =" + user1.hashCode()); System.out.println("user2.hashcode =" + user2.hashCode()); System.out.println("uesr1.equals(user2) is " + user1.equals(user2)); System.out.println("set.size = " + set.size()); /** * 在使用HashMap,HashSet时,经过比较hahscode的值来判断是否相等 * 运行结果 * user1.hashcode =1023487453 * user2.hashcode =1865127310 * uesr1.equals(user2) is false * set.size = 2 */ } @Test public void testHashCodeOverride() { UserOverride user1 = new UserOverride(1, "jack"); UserOverride user2 = new UserOverride(1, "jack"); HashSet<UserOverride> set = new HashSet<>(); set.add(user1); set.add(user2); System.out.println("user1.hashcode =" + user1.hashCode()); System.out.println("user2.hashcode =" + user2.hashCode()); System.out.println("uesr1.equals(user2) is " + user1.equals(user2)); System.out.println("set.size =" + set.size()); /** * 在使用HashMap,HashSet时,经过比较hahscode的值来判断是否相等 * 运行结果 * user1.hashcode =3254238 * user2.hashcode =3254238 * uesr1.equals(user2) is true * set.size =1 */ } @Test public void testEquals() { int i1 = 127, i2 = 127; Integer ibox1 = 128, ibox2 = 128; System.out .println("int i1 = 127,i2 = 127; --> i1 == i2 is " + (i1 == i2)); System.out.println( "Integer ibox1 = 128, ibox2 = 128; --> ibox1 == ibox2 is " + (ibox1 == ibox2)); System.out.println( "Integer ibox1 = 128, ibox2 = 128; --> ibox1.equals(ibox2) is " + ibox1.equals(ibox2)); /** * 由于Integer在重写equals方法时, * 执行结果 * int i1 = 127,i2 = 127; --> i1 == i2 is true * Integer ibox1 = 128, ibox2 = 128; --> ibox1 == ibox2 is false * Integer ibox1 = 128, ibox2 = 128; --> ibox1.equals(ibox2) is true */ } @Test public void testCloneShallow() throws CloneNotSupportedException { Role role = new Role(1, "normal"); User user = new User(1, "jack"); user.setRole(role); User userClone; userClone = (User) user.clone(); System.out.println("user.equals(userClone) is " + user.equals(userClone)); System.out.println("user == userClone is " + (user == userClone)); System.out.println( "user.getRole() == userClone.getRole() is " + (user.getRole() == userClone.getRole())); System.out.println("------------ 分割线 -----------"); user.getRole().setRoleName(user.getRole().getRoleName().toUpperCase()); System.out.println("user.getRole().getRoleName() is " + user.getRole().getRoleName()); System.out.println("userClone.getRole().getRoleName() is " + userClone.getRole().getRoleName()); /** * 此处的user.clone()为浅拷贝,因此user和userClone的UserOverride是指向同一内存地址的对象 * 执行结果 * 由于User没有重写equals方法,因此 equals的结果跟== 都为false * user.equals(userClone) is false * user == userClone is false * user.getRole() == userClone.getRole() is true * ------------ 分割线 ----------- * user.getRole().getRoleName() is NORMAL * userClone.getRole().getRoleName() is NORMAL */ } @Test public void testCloneDeep() throws CloneNotSupportedException { RoleOverride role = new RoleOverride(1, "normal"); UserOverride user = new UserOverride(1, "jack"); user.setRoleOverride(role); UserOverride userClone; userClone = (UserOverride) user.clone(); System.out.println("user.equals(userClone) is " + user.equals(userClone)); System.out.println("user == userClone is " + (user == userClone)); System.out.println("they'er getUserOverride is " + (user.getRoleOverride() == userClone.getRoleOverride())); System.out.println("------------ 分割线 -----------"); user.getRoleOverride().setRoleName(user.getRoleOverride().getRoleName().toUpperCase()); System.out.println("user.getRole().getRoleName() is " + user.getRoleOverride().getRoleName()); System.out.println( "userClone.getRole().getRoleName() is " + userClone.getRoleOverride().getRoleName()); /** * 此处的user.clone()为浅拷贝,因此user和userClone的UserOverride是指向同一内存地址的对象 * 执行结果 * 由于 RoleOverride 重写了equals方法,因此 equals的结果为true, == 结果为 false * user.equals(userClone) is true * user == userClone is false * they'er getUserOverride is false * ------------ 分割线 ----------- * user.getRole().getRoleName() is NORMAL * userClone.getRole().getRoleName() is normal */ } /** * 来自博客 https://blog.csdn.net/u014658905/article/details/81035870 */ @Test public void testNotifyAll() throws InterruptedException { final NotificationTest test = new NotificationTest(); Runnable waitTask = () -> { try { test.shouldGo(); } catch (InterruptedException ex) { System.out.println(ex.getMessage()); } System.out.println(Thread.currentThread().getName() + " finished Execution"); }; Runnable notifyTask = () -> { test.go(); System.out.println(Thread.currentThread().getName() + " finished Execution"); }; Thread t1 = new Thread(waitTask, "WT1"); //will wait Thread t2 = new Thread(waitTask, "WT2"); //will wait Thread t3 = new Thread(waitTask, "WT3"); //will wait Thread t4 = new Thread(notifyTask, "NT1"); //will notify //starting all waiting thread t1.start(); t2.start(); t3.start(); //pause to ensure all waiting thread started successfully sleep(200); //starting notifying thread t4.start(); /** * 运行结果 * WT1 is going to wait on this object * WT2 is going to wait on this object * WT3 is going to wait on this object * NT1 is going to notify all or one thread waiting on this object * NT1 finished Execution * WT3 is woken up * WT3 finished Execution * WT2 is woken up * WT2 is going to wait on this object * WT1 is woken up * WT1 is going to wait on this object */ } /** * 来自博客 https://blog.csdn.net/u014658905/article/details/81035870 */ @Test public void testNotify() throws InterruptedException { final NotificationTest test = new NotificationTest(); Runnable waitTask = () -> { try { test.shouldGo(); } catch (InterruptedException ex) { System.out.println(ex.getMessage()); } System.out.println(Thread.currentThread().getName() + " finished Execution"); }; Runnable notifyTask = () -> { test.go2(); System.out.println(Thread.currentThread().getName() + " finished Execution"); }; Thread t1 = new Thread(waitTask, "WT1"); //will wait Thread t2 = new Thread(waitTask, "WT2"); //will wait Thread t3 = new Thread(waitTask, "WT3"); //will wait Thread t4 = new Thread(notifyTask, "NT1"); //will notify //starting all waiting thread t1.start(); t2.start(); t3.start(); //pause to ensure all waiting thread started successfully sleep(200); //starting notifying thread t4.start(); /** * 运行结果 * WT1 is going to wait on this object * WT2 is going to wait on this object * WT3 is going to wait on this object * NT1 is going to notify all or one thread waiting on this object * NT1 finished Execution * WT1 is woken up * WT1 finished Execution */ } /** * 除了耗时完成后自动唤醒,还能够被notify和notifyAll唤醒 notify和notifyAll唤醒方式,如上面的例子所示 */ @Test public void testWait() throws InterruptedException { Runnable myThread = () -> { synchronized (this) { try { System.out .println("myThread start at " + new SimpleDateFormat("mm:ss").format(new Date())); //wait(5000);//5秒钟以后唤醒当前线程.继续执行 wait();//一直等待 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("myThread run end"); } }; Thread t1 = new Thread(myThread, "t1"); //will wait synchronized (t1) { t1.start(); t1.wait(2000); //2秒钟以后,唤醒了main线程继续执行 //t1.wait(2000,1000);//1000000*2000+1000 毫微秒钟以后,唤醒了main线程,彻底体现不出来这第二个参数的意义 //t1.wait();//mian线程一直等待,没有被其余线程唤醒 System.out .println("mainThread wake up at " + new SimpleDateFormat("mm:ss").format(new Date())); System.out.println("main run end"); } /** * 运行结果以下 * 当myThread被提早唤醒时,后面的代码不会被执行 * myThread start at 38:57 * myThread run end * mainThread wake up at 39:02 * main run end * 或 *myThread start at 41:52 * mainThread wake up at 41:54 * main run end */ } /** * 很经典的GC回收机制实例 */ @Test public void testFinalize() throws InterruptedException { // 新建对象,由于SAVE_HOOK指向这个对象,对象此时的状态是(reachable,unfinalized) GC.SAVE_HOOK = new GC(); //将SAVE_HOOK设置成null,此时刚才建立的对象就不可达了,由于没有句柄再指向它了,对象此时状态是(unreachable,unfinalized) GC.SAVE_HOOK = null; //强制系统执行垃圾回收,系统发现刚才建立的对象处于unreachable状态,并检测到这个对象的类覆盖了finalize方法,所以把这个对象放入F-Queue队列,由低优先级线程执行它的finalize方法,此时对象的状态变成(unreachable, finalizable)或者是(finalizer-reachable,finalizable) System.gc(); // sleep,目的是给低优先级线程从F-Queue队列取出对象并执行其finalize方法提供机会。在执行完对象的finalize方法中的super.finalize()时,对象的状态变成(unreachable,finalized)状态,但接下来在finalize方法中又执行了SAVE_HOOK = this;这句话,又有句柄指向这个对象了,对象又可达了。所以对象的状态又变成了(reachable, finalized)状态。 Thread.sleep(500); // 这里楼主说对象处于(reachable,finalized)状态应该是合理的。对象的finalized方法被执行了,所以是finalized状态。又由于在finalize方法是执行了SAVE_HOOK=this这句话,原本是unreachable的对象,又变成reachable了。 if (null != GC.SAVE_HOOK) { //此时对象应该处于(reachable, finalized)状态 // 这句话会输出,注意对象由unreachable,通过finalize复活了。 System.out.println("Yes , I am still alive"); } else { System.out.println("No , I am dead"); } // 再一次将SAVE_HOOK放空,此时刚才复活的对象,状态变成(unreachable,finalized) GC.SAVE_HOOK = null; // 再一次强制系统回收垃圾,此时系统发现对象不可达,虽然覆盖了finalize方法,但已经执行过了,所以直接回收。 System.gc(); // 为系统回收垃圾提供机会 Thread.sleep(500); if (null != GC.SAVE_HOOK) { // 这句话不会输出,由于对象已经完全消失了。 System.out.println("Yes , I am still alive"); } else { System.out.println("No , I am dead"); } } /** * 比较obj.hashCode 和系统的 System.identityHashCode(obj)的不一样 * obj.hashCode比较的是值,是obj重写的hashCode方法, * System.identityHashCode是将obj的存储位置转换成为hashCode */ @Test public void testSystemHashCode() throws CloneNotSupportedException { User u1 = new User(1,"jack"); User u2 = new User(1,"jack"); Role role = new Role(1,"normal"); u1.setRole(role); u2.setRole(role); User u1Clone = (User) u1.clone();//此处为浅拷贝,user.getRole指向的是同一个内存地址 System.out.println("System.identityHashCode(u1)=="+System.identityHashCode(u1.getRole())); System.out.println("System.identityHashCode(u1Clone)=="+System.identityHashCode(u1Clone.getRole())); System.out.println("System.identityHashCode(u2)=="+System.identityHashCode(u2.getRole())); System.out.println("--------------- 分割线 --------------"); UserOverride u3 = new UserOverride(1, "jack"); UserOverride u4 = new UserOverride(1, "jack"); RoleOverride r1 = new RoleOverride(1,"normal"); u3.setRoleOverride(r1); u4.setRoleOverride(r1); //此处是深克隆,u3.getRoleOverride是指向不一样的物理地址 UserOverride u3Clone = (UserOverride) u3.clone(); System.out.println("System.identityHashCode(u3)=="+System.identityHashCode(u3.getRoleOverride())); System.out.println("System.identityHashCode(u3Clone)=="+System.identityHashCode(u3Clone.getRoleOverride())); System.out.println("System.identityHashCode(u4)=="+System.identityHashCode(u4.getRoleOverride())); /** * 运行结果 * System.identityHashCode(u1)==1023487453 * System.identityHashCode(u1Clone)==1023487453 * System.identityHashCode(u2)==1023487453 * --------------- 分割线 -------------- * System.identityHashCode(u3)==1865127310 * System.identityHashCode(u3Clone)==515132998 * System.identityHashCode(u4)==1865127310 */ } private class User implements Cloneable { private int userId; private String userName; private Role role; User() { } User(int userId, String userName) { this.userId = userId; this.userName = userName; } Role getRole() { return role; } void setRole(Role role) { this.role = role; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } } private class UserOverride implements Cloneable { private int userId; private String userName; private RoleOverride roleOverride; UserOverride(int userId, String userName) { this.userId = userId; this.userName = userName; } RoleOverride getRoleOverride() { return roleOverride; } void setRoleOverride(RoleOverride roleOverride) { this.roleOverride = roleOverride; } @Override public int hashCode() { return userName.hashCode() ^ userId; } @Override public boolean equals(Object obj) { if (obj == null) { return false; } //若是是同一个对象返回true,反之返回false if (this == obj) { return true; } //判断是否类型相同 if (this.getClass() != obj.getClass()) { return false; } UserOverride person = (UserOverride) obj; return userName.equals(person.userName) && userId == person.userId; } @Override protected Object clone() throws CloneNotSupportedException { Object clone = super.clone(); RoleOverride roleOverride = ((UserOverride) clone).getRoleOverride(); ((UserOverride) clone).setRoleOverride((RoleOverride) roleOverride.clone()); return clone; } } private class Role { private int roleId; private String roleName; Role(int roleId, String roleName) { this.roleId = roleId; this.roleName = roleName; } String getRoleName() { return roleName; } void setRoleName(String roleName) { this.roleName = roleName; } } private class RoleOverride implements Cloneable { private int roleId; private String roleName; RoleOverride(int roleId, String roleName) { this.roleId = roleId; this.roleName = roleName; } String getRoleName() { return roleName; } void setRoleName(String roleName) { this.roleName = roleName; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } } private class NotificationTest { private volatile boolean go = false; synchronized void shouldGo() throws InterruptedException { while (go != true) { System.out.println(Thread.currentThread().getName() + " is going to wait on this object"); wait(); //release lock and reacquires on wakeup System.out.println(Thread.currentThread().getName() + " is woken up"); } go = false; //resetting condition } /* * both shouldGo() and go() are locked on current object referenced by "this" keyword */ synchronized void go() { while (go == false) { System.out.println(Thread.currentThread().getName() + " is going to notify all or one thread waiting on this object"); go = true; //making condition true for waiting thread //notify(); // only one out of three waiting thread WT1, WT2,WT3 will woke up notifyAll(); // all waiting thread WT1, WT2,WT3 will woke up } } synchronized void go2() { while (go == false) { System.out.println(Thread.currentThread().getName() + " is going to notify all or one thread waiting on this object"); go = true; //making condition true for waiting thread notify(); // only one out of three waiting thread WT1, WT2,WT3 will woke up //notifyAll(); // all waiting thread WT1, WT2,WT3 will woke up } } } private static class GC { static GC SAVE_HOOK = null; @Override protected void finalize() throws Throwable { super.finalize(); System.out.println("execute method finalize()"); // 这句话让对象的状态由unreachable变成reachable,就是对象复活 SAVE_HOOK = this; } } }
下一章节传送门 --> jdk8源码分析笔记1 --> Object.class