第一章節,不能再往前了!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