原創轉載請注明出處:https://www.cnblogs.com/agilestyle/p/11488192.html
從JDK1.2開始,就提供了四種類型的引用:強引用、軟引用、弱引用和虛引用。
Java中提供這四種引用類型主要有兩個目的:第一是可以讓程序員通過代碼的方式決定某些對象的生命周期;第二是有利於JVM進行垃圾回收。
強引用(StrongReference)
強引用就是指在程序代碼之中普遍存在的,比如下面這段代碼中的object和str都是強引用:
1 Object object = new Object(); 2 String str = "hello";
只要某個對象有強引用與之關聯,JVM必定不會回收這個對象,即使在內存不足的情況下,JVM寧願拋出OutOfMemory錯誤也不會回收這種對象。
1 package org.fool.reference; 2 3 public class StrongReferenceTest { 4 public static void main(String[] args) { 5 new StrongReferenceTest().test(); 6 } 7 8 public void test() { 9 /** 10 * 強引用就是指在程序代碼之中普遍存在的,比如下面這段代碼中的object和objects都是強引用 11 * 只要某個對象有強引用與之關聯,JVM必定不會回收這個對象,即使在內存不足的情況下, 12 * JVM寧願拋出OutOfMemory錯誤也不會回收這種對象 13 */ 14 Object object = new Object(); 15 Object[] objects = new Object[100]; 16 /** 17 * 當運行至Object[] objArr = new Object[100];這句時,如果內存不足,JVM會拋出OOM錯誤也不會回收object指向的對象。 18 * 不過要注意的是,當test運行完之后,object和objects都已經不存在了,所以它們指向的對象都會被JVM回收。 19 * 如果想中斷強引用和某個對象之間的關聯,可以顯示地將引用賦值為null,這樣一來的話,JVM在合適的時間就會回收該對象。 20 */ 21 } 22 }
軟引用(SoftReference)
軟引用是用來描述一些有用但並不是必需的對象,在Java中用java.lang.ref.SoftReference類來表示。對於軟引用關聯着的對象,只有在內存不足的時候JVM才會回收該對象。
1 package org.fool.reference; 2 3 import java.lang.ref.SoftReference; 4 5 public class SoftRefereneceTest { 6 public static void main(String[] args) { 7 /** 8 * 軟引用是用來描述一些有用但並不是必需的對象,在Java中用java.lang.ref.SoftReference類來表示。 9 * 對於軟引用關聯着的對象,只有在內存不足的時候JVM才會回收該對象。因此,這一點可以很好地用來解決OOM的問題, 10 * 並且這個特性很適合用來實現緩存:比如網頁緩存、圖片緩存等。 11 * 軟引用可以和一個引用隊列(ReferenceQueue)聯合使用,如果軟引用所引用的對象被JVM回收,這個軟引用就會被加入到與之關聯的引用隊列中。 12 */ 13 SoftReference<String> sr = new SoftReference<>(new String("hello")); 14 15 System.out.println(sr.get()); // hello 16 17 System.gc(); 18 19 System.out.println(sr.get()); // hello 20 } 21 }
弱引用(WeakReference)
弱引用也是用來描述非必需對象的,當JVM進行垃圾回收時,無論內存是否充足,都會回收被弱引用關聯的對象。在java中,用java.lang.ref.WeakReference類來表示。
1 package org.fool.reference; 2 3 import java.lang.ref.WeakReference; 4 5 public class WeakReferenceTest { 6 public static void main(String[] args) { 7 /** 8 * 弱引用也是用來描述非必需對象的,當JVM進行垃圾回收時,無論內存是否充足,都會回收被弱引用關聯的對象。 9 * 在java中,用java.lang.ref.WeakReference類來表示。 10 */ 11 WeakReference<String> wr = new WeakReference<>(new String("hello")); 12 13 System.out.println(wr.get()); // hello 14 15 System.gc(); 16 17 System.out.println(wr.get()); // null 18 /** 19 * 第二個輸出結果是null,這說明只要JVM進行垃圾回收,被弱引用關聯的對象必定會被回收掉。 20 * 不過要注意的是,這里所說的被弱引用關聯的對象是指只有弱引用與之關聯, 21 * 如果存在強引用同時與之關聯,則進行垃圾回收時也不會回收該對象(軟引用也是如此)。 22 * 弱引用可以和一個引用隊列(ReferenceQueue)聯合使用, 23 * 如果弱引用所引用的對象被JVM回收,這個軟引用就會被加入到與之關聯的引用隊列中。 24 */ 25 } 26 }
虛引用(PhantomReference)
虛引用和前面的軟引用、弱引用不同,它並不影響對象的生命周期。在java中用java.lang.ref.PhantomReference類表示。如果一個對象與虛引用關聯,則跟沒有引用與之關聯一樣,在任何時候都可能被垃圾回收器回收。
1 package org.fool.reference; 2 3 import java.lang.ref.PhantomReference; 4 import java.lang.ref.ReferenceQueue; 5 6 public class PhantomReferenceTest { 7 public static void main(String[] args) { 8 /** 9 * 虛引用和前面的軟引用、弱引用不同,它並不影響對象的生命周期。在java中用java.lang.ref.PhantomReference類表示。 10 * 如果一個對象與虛引用關聯,則跟沒有引用與之關聯一樣,在任何時候都可能被垃圾回收器回收。 11 * 要注意的是,虛引用必須和引用隊列關聯使用,當垃圾回收器准備回收一個對象時, 12 * 如果發現它還有虛引用,就會把這個虛引用加入到與之 關聯的引用隊列中。 13 * 程序可以通過判斷引用隊列中是否已經加入了虛引用,來了解被引用的對象是否將要被垃圾回收。 14 * 如果程序發現某個虛引用已經被加入到引用隊列,那么就可以在所引用的對象的內存被回收之前采取必要的行動。 15 */ 16 17 ReferenceQueue<String> queue = new ReferenceQueue<>(); 18 19 PhantomReference<String> pr = new PhantomReference<>(new String("hello"), queue); 20 21 System.out.println(pr.get()); // null 22 23 System.gc(); 24 25 System.out.println(pr.get()); // null 26 } 27 }
對於強引用,我們平時在編寫代碼時經常會用到。而對於其他三種類型的引用,使用得最多的就是軟引用和弱引用,這兩種既有相似之處又有區別。它們都是用來描述非必需對象的,但是被軟引用關聯的對象只有在內存不足時才會被回收,而被弱引用關聯的對象在JVM進行垃圾回收時總會被回收。
在SoftReference類中,有三個方法,兩個構造方法(WeakReference類似)和一個get方法:
get方法用來獲取與軟引用關聯的對象的引用,如果該對象被回收了,則返回null。
在WeakReference類中,有兩個方法,兩個構造方法
在使用軟引用和弱引用的時候,我們可以顯示地通過System.gc()來通知JVM進行垃圾回收,但是要注意的是,雖然發出了通知,JVM不一定會立刻執行,也就是說這句是無法確保此時JVM一定會進行垃圾回收的。
Reference
http://www.cnblogs.com/dolphin0520/p/3784171.html