search
尋找貓咪~QQ 地點 桃園市桃園區 Taoyuan , Taoyuan

Java中 四種引用(強引用 軟引用 弱引用 虛引用)

這就是引用嗎?

Class A = new Class;

沒錯,這就是引用。這也是我們經常見到的一種引用類型。這也是強引用。下面來詳細看看它。

強引用(Strong Reference)

上文提到的這種就是強引用,只要強引用存在,JVM寧願拋出異常,垃圾回收器(Garbage collected Heap,GC 堆)也不會回收被引用的對象。

強引用帶來的問題

也許,你在開發中會遇到這樣一個場景:你想使用Widget這個類,但是這個類不能被繼承,所以你無法添加新的功能。

但是,我們想追蹤widget對象的額外信息,假如我們想為每個widget實體加上一個id屬性,以便進行區分。而widget類並沒有id屬性,也不能擴展追加id屬性,怎麼辦呢?

聰明的你,可能想到HashMap,沒錯,確實是個好主意。

HashMap<String, Widget> widgetHashMap = new HashMap<String, Widget>; widgetHashMap.put("001", new Widget);

這表面看上去沒有問題,但是widget對象的強引用很有可能會引發問題。我們可以確信當一個widget序列號不需要時,我們應該將這個條目從map中移除。如果我們沒有移除的話,可能會導致內存泄露,亦或者我們手動移除時刪除了我們正在使用的widgets,會導致有效數據的丟失。其實這些問題很類似,這就是沒有垃圾回收機制的語言管理內存時常遇到的問題。但是我們不用去擔心這個問題,因為我們使用的時具有垃圾回收機制的Java語言。

另一個強引用可能帶來的問題就是緩存,尤其是像圖片這樣的大文件的緩存。假設你有一個程序需要處理用戶提供的圖片,通常的做法就是做圖片數據緩存,因為從磁碟載入圖片代價很大,並且同時我們也想避免在內存中同時存在兩份一樣的圖片數據。

緩存被設計的目的就是避免我們去再次載入哪些不需要的文件。你會很快發現在緩存中會一直包含一個到已經指向內存中圖片數據的引用。使用強引用會強製圖片數據留在內存,這就需要你來決定什麼時候圖片數據不需要並且手動從緩存中移除,進而可以讓垃圾回收器回收。因此你再一次被強製做垃圾回收器該做的工作,並且人為決定是該清理到哪一個對象。

弱引用(WeakReference)

弱引用簡單來說就是將對象留在內存的能力不是那麼強的引用。使用WeakReference,垃圾回收器會幫你來決定引用的對象何時回收並且將對象從內存移除。

創建弱引用如下:

Widget widget = new Widget; WeakReference<Widget> widgetWeakReference = new WeakReference<Widget>(widget);

解決上述的widget序列數記錄的問題,最簡單的辦法就是使用Java內置的WeakHashMap類。WeakHashMap和HashMap幾乎一樣,唯一的區別就是它的鍵(不是值!!!)使用WeakReference引用。當WeakHashMap的鍵標記為垃圾的時候,這個鍵對應的條目就會自動被移除。這就避免了上面不需要的Widget對象手動刪除的問題。使用WeakHashMap可以很便捷地轉為HashMap或者Map。

下面看一個弱引用示例:

package com.company;import java.lang.ref.WeakReference;public class Main { public static void main(String args) { Widget w = new Widget;//w是新建的Widget的強引用 WeakReference<Widget> widgetWeakReference = new WeakReference<Widget>(w);//將一個軟引用指向對象,此時Widget對象有兩個引用 w = null;//去除對象的強引用 System.gc;//gc對弱引用對象進行回收 } }class Widget { }

解決上述的widget序列數記錄的問題,最簡單的辦法就是使用Java內置的WeakHashMap類。WeakHashMap和HashMap幾乎一樣,唯一的區別就是它的鍵(不是值!!!)使用WeakReference引用。當WeakHashMap的鍵標記為垃圾的時候,這個鍵對應的條目就會自動被移除。這就避免了上面不需要的Widget對象手動刪除的問題。使用WeakHashMap可以很便捷地轉為HashMap或者Map。

引用隊列(Reference Queue)

一旦弱引用對象開始返回null,該弱引用指向的對象就被標記成了垃圾。而這個弱引用對象(非其指向的對象)就沒有什麼用了。通常這時候需要進行一些清理工作。比如WeakHashMap會在這時候移除沒用的條目來避免保存無限制增長的沒有意義的弱引用。

引用隊列可以很容易地實現跟蹤不需要的引用。當你在構造WeakReference時傳入一個ReferenceQueue對象,當該引用指向的對象被標記為垃圾的時候,這個引用對象會自動地加入到引用隊列裡面。接下來,你就可以在固定的周期,處理傳入的引用隊列,比如做一些清理工作來處理這些沒有用的引用對象。

四種引用

在Java 1.2 之後,Java地引用的概念進行了補充,以前只有被引用和沒有被引用兩種狀態。擴充之後分為四種,

1. 強引用(Strong Reference)

2. 軟引用(Soft Reference)

3. 弱引用(WeakReference)

4. 虛引用(Phantom Reference),也稱幽靈引用或者幻影引用

軟引用(Soft Reference)

如果一個對象只具有軟引用,則內存空間足夠,垃圾回收器就不會回收它;如果內存空間不足了,就會回收這些對象的內存。只要垃圾回收器沒有回收它, 該對象就可以被程序使用。軟引用可用來實現內存敏感的高速緩存。

package com.company;import java.lang.ref.WeakReference;public class Main { public static void main(String args) { Widget w = new Widget;//w是新建的Widget的強引用 WeakReference<Widget> widgetWeakReference = new WeakReference<Widget>(w);//將一個軟引用指向對象,此時Widget對象有兩個引用 w = null;//去除對象的強引用 System.gc;//gc只有在內存不足是才會回收軟引用對象 } }class Widget { }

虛引用(Phantom Reference)

與軟引用,弱引用不同,虛引用指向的對象十分脆弱,我們不可以通過get方法來得到其指向的對象。它的唯一作用就是當其指向的對象被回收之後,自己被加入到引用隊列,用作記錄該引用指向的對象已被銷毀。

虛引用只有在其指向的對象從內存中移除掉之後才會加入到引用隊列中。其get方法一直返回null就是為了阻止其指向的幾乎被銷毀的對象重新復活。

學習Java的同學注意了!!!

學習過程中遇到什麼問題或者想獲取學習資源的話,歡迎加入Java學習交流群,群號碼:392216227我們一起學Java!



熱門推薦

本文由 yidianzixun 提供 原文連結

寵物協尋 相信 終究能找到回家的路
寫了7763篇文章,獲得2次喜歡
留言回覆
回覆
精彩推薦