java reference 傳引用_Java的引用(reference)---Roni

摘自《Java面向對象編程》一書,作者:孫衛琴 來源:www.javathinker.org

在JDK1.2以前的版本中,當一個對象不被任何變量引用,那么程序就無法再使用這個對象。也就是說,只有對象處于可觸及狀態,程序才能使用它。這就像在日常生活中,從商店購買了某樣物品后,如果有用,就一直保留它,否則就把它扔到垃圾箱,由清潔工人收走。一般說來,如果物品已經被扔到垃圾箱,想再把它撿回來使用就不可能了。

但有時候情況并不這么簡單,你可能會遇到類似雞肋一樣的物品,食之無味,棄之可惜。這種物品現在已經無用了,保留它會占空間,但是立刻扔掉它也不劃算,因為也許將來還會派用場。對于這樣的可有可無的物品,一種折衷的處理辦法是:如果家里空間足夠,就先把它保留在家里,如果家里空間不夠,即使把家里所有的垃圾清除,還是無法容納那些必不可少的生活用品,那么再扔掉這些可有可無的物品。

從JDK1.2版本開始,把對象的引用分為四種級別,從而使程序能更加靈活的控制對象的生命周期。這四種級別由高到低依次為:強引用、軟引用、弱引用和虛引用。

以下用紅標注地方為各級別的特點(Roni)

1.強引用

本章前文介紹的引用實際上都是強引用,這是使用最普遍的引用。如果一個對象具有強引用,那就類似于必不可少的生活用品,垃圾回收器絕不會回收它。當內存空間不足,Java虛擬機寧愿拋出OutOfMemoryError錯誤,使程序異常終止,也不會靠隨意回收具有強引用的對象來解決內存不足問題。

2.軟引用(SoftReference)

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

軟引用可以和一個引用隊列(ReferenceQueue)聯合使用,如果軟引用所引用的對象被垃圾回收,Java虛擬機就會把這個軟引用加入到與之關聯的引用隊列中。

3.弱引用(WeakReference)

如果一個對象只具有弱引用,那就類似于可有可物的生活用品。弱引用與軟引用的區別在于:只具有弱引用的對象擁有更短暫的生命周期。在垃圾回收器線程掃描它所管轄的內存區域的過程中,一旦發現了只具有弱引用的對象,不管當前內存空間足夠與否,都會回收它的內存。不過,由于垃圾回收器是一個優先級很低的線程,因此不一定會很快發現那些只具有弱引用的對象。

弱引用可以和一個引用隊列(ReferenceQueue)聯合使用,如果弱引用所引用的對象被垃圾回收,Java虛擬機就會把這個弱引用加入到與之關聯的引用隊列中。

4.虛引用(PhantomReference)

"虛引用"顧名思義,就是形同虛設,與其他幾種引用都不同,虛引用并不會決定對象的生命周期。如果一個對象僅持有虛引用,那么它就和沒有任何引用一樣,在任何時候都可能被垃圾回收。

虛引用主要用來跟蹤對象被垃圾回收的活動。虛引用與軟引用和弱引用的一個區別在于:虛引用必須和引用隊列(ReferenceQueue)聯合使用。當垃圾回收器準備回收一個對象時,如果發現它還有虛引用,就會在回收對象的內存之前,把這個虛引用加入到與之關聯的引用隊列中。程序可以通過判斷引用隊列中是否已經加入了虛引用,來了解被引用的對象是否將要被垃圾回收。程序如果發現某個虛引用已經被加入到引用隊列,那么就可以在所引用的對象的內存被回收之前采取必要的行動。

在本書中,"引用"既可以作為動詞,也可以作為名詞,讀者應該根據上下文來區分"引用"的含義。

在java.lang.ref包中提供了三個類:SoftReference類、WeakReference類和PhantomReference類,它們分別代表軟引用、弱引用和虛引用。ReferenceQueue類表示引用隊列,它可以和這三種引用類聯合使用,以便跟蹤Java虛擬機回收所引用的對象的活動。以下程序創建了一個String對象、ReferenceQueue對象和WeakReference對象:

//創建一個強引用

String str = new String("hello");

//創建引用隊列,

為范型標記,表明隊列中存放String對象的引用

ReferenceQueue rq = new

ReferenceQueue();

//創建一個弱引用,它引用"hello"對象,并且與rq引用隊列關聯

//為范型標記,表明WeakReference會弱引用String對象

WeakReference wf = new

WeakReference(str,

rq);

以上程序代碼執行完畢,內存中引用與對象的關系如圖11-10所示。

a4c26d1e5885305701be709a3d33442f.png

圖11-10 "hello"對象同時具有強引用和弱引用

在圖11-10中,帶實線的箭頭表示強引用,帶虛線的箭頭表示弱引用。從圖中可以看出,此時"hello"對象被str強引用,并且被一個WeakReference對象弱引用,因此"hello"對象不會被垃圾回收。

在以下程序代碼中,把引用"hello"對象的str變量置為null,然后再通過WeakReference弱引用的get()方法獲得"hello"對象的引用:

String str = new String("hello"); //①

ReferenceQueue rq = new

ReferenceQueue(); //②

WeakReference wf = new

WeakReference(str, rq);

//③

str=null; //④取消"hello"對象的強引用

String str1=wf.get(); //⑤假如"hello"對象沒有被回收,str1引用"hello"對象

//假如"hello"對象沒有被回收,rq.poll()返回null

Reference extends String>

ref=rq.poll(); //⑥

執行完以上第④行后,內存中引用與對象的關系如圖11-11所示,此時"hello"對象僅僅具有弱引用,因此它有可能被垃圾回收。假如它還沒有被垃圾回收,那么接下來在第⑤行執行wf.get()方法會返回

"hello"對象的引用,并且使得這個對象被str1強引用。再接下來在第⑥行執行rq.poll()方法會返回null,因為此時引用隊列中沒有任何引用。ReferenceQueue的poll()方法用于返回隊列中的引用,如果沒有則返回null。

a4c26d1e5885305701be709a3d33442f.png

圖11-11 "hello"對象只具有弱引用

在以下程序代碼中,執行完第④行后,"hello"對象僅僅具有弱引用。接下來兩次調用System.gc()方法,催促垃圾回收器工作,從而提高

"hello"對象被回收的可能性。假如"hello"對象被回收,那么WeakReference對象的引用被加入到ReferenceQueue中,接下來wf.get()方法返回null,并且rq.poll()方法返回WeakReference對象的引用。圖11-12顯示了執行完第⑧行后內存中引用與對象的關系。

String str = new String("hello"); //①

ReferenceQueue rq = new

ReferenceQueue(); //②

WeakReference wf = new

WeakReference(str, rq);

//③

str=null; //④

//兩次催促垃圾回收器工作,提高"hello"對象被回收的可能性

System.gc(); //⑤

System.gc(); //⑥

String str1=wf.get(); //⑦ 假如"hello"對象被回收,str1為null

Reference extends String>

ref=rq.poll(); //⑧

a4c26d1e5885305701be709a3d33442f.png

圖11-12 "hello"對象被垃圾回收,弱引用被加入到引用隊列

在以下例程11-15的References類中,依次創建了10個軟引用、10個弱引用和10個虛引用,它們各自引用一個Grocery

對象。從程序運行時的打印結果可以看出,虛引用形同虛設,它所引用的對象隨時可能被垃圾回收,具有弱引用的對象擁有稍微長的生命周期,當垃圾回收器執行回收操作時,有可能被垃圾回收,具有軟引用的對象擁有較長的生命周期,但在Java虛擬機認為內存不足的情況下,也會被垃圾回收。

例程11-15 References.java

import java.lang.ref.*;

import java.util.*;

class Grocery{

private static final int SIZE = 10000;

//屬性d使得每個Grocery對象占用較多內存,有80K左右

private double[] d = new double[SIZE];

private String id;

public Grocery(String id) { this.id = id; }

public String toString() { return id; }

public void finalize() {

System.out.println("Finalizing " + id);

}

}

public class References {

private static

ReferenceQueue rq = new

ReferenceQueue();

public static void checkQueue() {

Reference extends Grocery> inq =

rq.poll(); //從隊列中取出一個引用

if(inq != null)

System.out.println("In queue: "+inq+" : "+inq.get());

}

public static void main(String[] args) {

final int size=10;

//創建10個Grocery對象以及10個軟引用

Set>

sa = new

HashSet>();

for(int i = 0; i < size; i++) {

SoftReference ref=

new SoftReference(new

Grocery("Soft " + i), rq);

System.out.println("Just created: " +ref.get());

sa.add(ref);

}

System.gc();

checkQueue();

//創建10個Grocery對象以及10個弱引用

Set>

wa = new

HashSet>();

for(int i = 0; i < size; i++) {

WeakReference ref=

new WeakReference(new

Grocery("Weak " + i), rq);

System.out.println("Just created: " +ref.get());

wa.add(ref);

}

System.gc();

checkQueue();

//創建10個Grocery對象以及10個虛引用

Set>

pa = new

HashSet>();

for(int i = 0; i < size; i++) {

PhantomReferenceref =

new PhantomReference(new

Grocery("Phantom " + i), rq);

System.out.println("Just created: " +ref.get());

pa.add(ref);

}

System.gc();

checkQueue();

}

}

在Java集合中有一種特殊的Map類型:WeakHashMap,在這種Map中存放了鍵對象的弱引用,當一個鍵對象被垃圾回收,那么相應的值對象的引用會從Map中刪除。WeakHashMap能夠節約存儲空間,可用來緩存那些非必須存在的數據。關于Map接口的一般用法,可參見本書第15章的15.4節(Map)。

以下例程11-16的MapCache類的main()方法創建了一個WeakHashMap對象,它存放了一組Key對象的弱引用,此外main()方法還創建了一個數組對象,它存放了部分Key對象的強引用。

例程11-16 MapCache.java

import java.util.*;

import java.lang.ref.*;

class Key {

String id;

public Key(String id) { this.id = id; }

public String toString() { return id; }

public int hashCode() {

return id.hashCode();

}

public boolean equals(Object r) {

return (r instanceof Key)

&& id.equals(((Key)r).id);

}

public void finalize() {

System.out.println("Finalizing Key "+ id);

}

}

class Value {

String id;

public Value(String id) { this.id = id; }

public String toString() { return id; }

public void finalize() {

System.out.println("Finalizing Value "+id);

}

}

public class MapCache {

public static void main(String[] args) throws Exception{

int size = 1000;

// 或者從命令行獲得size的大小

if(args.length > 0)size =

Integer.parseInt(args[0]);

Key[] keys = new Key[size]; //存放鍵對象的強引用

WeakHashMap whm = new

WeakHashMap();

for(int i = 0; i < size; i++) {

Key k = new Key(Integer.toString(i));

Value v = new Value(Integer.toString(i));

if(i % 3 == 0) keys[i] = k; //使Key對象持有強引用

whm.put(k, v); //使Key對象持有弱引用

}

//催促垃圾回收器工作

System.gc();

//把CPU讓給垃圾回收器線程

Thread.sleep(8000);

}

}

以上程序的部分打印結果如下:

Finalizing Key 998

Finalizing Key 997

Finalizing Key 995

Finalizing Key 994

Finalizing Key 992

Finalizing Key 991

Finalizing Key 989

Finalizing Key 988

Finalizing Key 986

Finalizing Key 985

Finalizing Key 983

從打印結果可以看出,當執行System.gc()方法后,垃圾回收器只會回收那些僅僅持有弱引用的Key對象。id可以被3整數的Key對象持有強引用,因此不會被回收。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/259627.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/259627.shtml
英文地址,請注明出處:http://en.pswp.cn/news/259627.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C# 以管理員身份運行程序

剛看了一篇博友寫的“以管理員身份運行程序”, 所以我也來寫一個簡單易懂的&#xff0c;簡單兩步搞定&#xff0c;不用寫任何代碼&#xff1a; 第一步&#xff1a; 右鍵選擇項目 > 添加 > 新建項 &#xff1b; 找到 應用程序清單文件&#xff0c;后綴名為manifest&#x…

會計轉行從事IT,如何在一年時間內全職學習?

2019獨角獸企業重金招聘Python工程師標準>>> https://www.zhihu.com/question/21427478/answer/18227060 轉載于:https://my.oschina.net/soho00147/blog/836138

VS2010中使用CL快速 生成DLL的方法

方案一&#xff1a; 1、命令行中輸入cl example.cpp&#xff0c;生成example.obj和example.lib文件。有可能還會提示“沒有入口點”的錯誤。這是因為我們的CPP中是要生成dll文件的&#xff0c;并沒有main()這樣的主函數作為入口點。如果是C文件&#xff0c;則輸入cl /c exampl…

java field 獲得值_反射通用獲取字段值

像之前回答的那樣&#xff0c;您應該使用&#xff1a;Object value field.get(objectInstance);有時更喜歡的另一種方法是動態調用getter。示例代碼&#xff1a;public static Object runGetter(Field field, BaseValidationObject o){// MZ: Find the correct methodfor (Met…

android 中如何模擬back鍵

主要是在使用Fragment時能夠返回前一級&#xff0c;所以才找到了這些資料。 有兩種方式可以實現&#xff0c;直接上代碼 方法1&#xff1a; public void onBack(){new Thread(){public void run() {try{Instrumentation inst new Instrumentation();inst.sendKeyDownUpSync(Ke…

如何生成后綴表達式

如果計算一個表達式&#xff0c;比如 456*2&#xff0c;隨著計算器的不同&#xff0c;簡單的四功能計算器是30&#xff0c;許多科學計算器知道乘法的優先級高于加法&#xff0c;所以科學答案是21。典型計算順序可以是計算45&#xff0c;存為臨時變量a&#xff0c;再計算6*2&…

【原生JS插件】LoadingBar頁面頂部加載進度條

先展示一下已經實現的效果&#xff1a; 預覽地址&#xff1a;http://dtdxrk.github.io/js-plug/LoadingBar/index.html 看到手機上的瀏覽器內置了頁面的加載進度條&#xff0c;想用在pc上。 網上搜了一下&#xff0c;看到幾種頁面loading的方法&#xff1a; 1.在body頭部加入lo…

qtp啟動java程序_轉: QTP六脈神劍之調用Java程序

查看( 1147 ) /評論( 21 )六脈神劍之調用程序0Xp1zLN_0版權聲明&#xff1a;原創作品&#xff0c;轉載請以鏈接方式注明出自http://www.51testing.com/?35&#xff0c;否則將追究法律責任。51Testing軟件測試網y|X,taS51Testing軟件測試網b;|w6I"g6oK本文出自songfun的51…

Linq 數據庫操作(增刪改查)

Linq數據庫增刪改查 Linq是一種查詢語言&#xff0c;集成包含在formwork中&#xff0c;包含在C#語言中&#xff0c;它的作用是降低查詢的門檻&#xff0c;提高開發效率&#xff0c;是我們必須掌握的技術之一&#xff0c;下面是我自己對linq數據庫操作的方法&#xff0c;與大家…

第八章 Python 對象和類

一、什么是對象 在 Pyth 中&#xff0c;對象就是經過實例化的&#xff0c;具體可以操作的一組代碼的組合&#xff1b; 對象一般包含數據&#xff08;變量&#xff0c;更習慣稱之為屬性 attribute&#xff09;&#xff0c;也包含代碼&#xff08;函數&#xff0c;也稱之為方法&a…

JS同名方法,

JS同名方法只會調用最后一個方法。 JS中同時綁定多個事件&#xff0c;先綁定的先調用。后綁定的后調用。轉載于:https://www.cnblogs.com/daishuguang/p/4169718.html

Spring WebSocket初探2 (Spring WebSocket入門教程)

2019獨角獸企業重金招聘Python工程師標準>>> WebSocket前端準備 SockJS&#xff1a; SockJS 是一個瀏覽器上運行的 JavaScript 庫&#xff0c;如果瀏覽器不支持 WebSocket&#xff0c;該庫可以模擬對 WebSocket 的支持&#xff0c;實現瀏覽器和 Web 服務器之間低延遲…

軟件測試相關概念與分類

這是我看了有關軟件測試的書的一些歸納與總結。 軟件測試的核心是發現軟件中的缺陷。測試是對軟件質量的度量。 一、缺陷 缺陷&#xff0c;目前沒有標準定義 。與缺陷相關的一組定義就有&#xff1a;軟件錯誤、軟件缺陷、軟件故障、軟件失效。 軟件錯誤&#xff1a;在軟件生存周…

excel SUBTOTAL函數使用詳解

轉自&#xff1a;http://www.kuqin.com/shuoit/20110524/91710.html 今天用Excel在進行業務統計時&#xff0c;遇到一個小問題&#xff0c;Google了一下&#xff0c;又學了一招。 一般人都會使用“自動篩選”功能&#xff0c;篩選完成后&#xff0c;會在表格左下角的狀態欄中提…

java九宮格問題課程設計_課程設計九宮格數獨.doc

課程設計九宮格數獨中南民族大學管理學院學生課程設計報告課題名稱&#xff1a; java課程設計選題名稱&#xff1a; 九宮格數獨年 級&#xff1a; 2009專 業&#xff1a; 信息管理與信息系統學 號&#xff1a;姓 名&#xff1a;指導教師&#xff1a;完成地點&#xff1a; 管理學…

Scrapy使用問題整理(轉載)

轉載自&#xff1a;http://blog.csdn.net/heu07111121/article/details/50832999最近嘗試使用Scrapy進行數據抓取&#xff0c;并嘗試在windows7 64位系統上安裝scrapy&#xff0c;下面總結記錄遇到兩個問題和解決方法&#xff1a;scrapy官網的地址為&#xff1a;http://scrapy.…

英文Ubantu系統安裝中文輸入法

以前都是安裝的中文Ubantu&#xff0c;但是有時候用命令行的時候中文識別不好&#xff0c;會出現錯誤&#xff0c;所以這次安裝了英文版&#xff0c;但是安裝后發現輸入法不好用&#xff0c;于是就要自己安裝輸入法。 安裝環境為Ubantu13.04 1.卸載Ubantu默認的ibus輸入法 sudo…

控制文件初探

1、個數和位置的管理&#xff08;因為控制文件時在參數文件定義的&#xff0c;所以可以直接修改參數文件&#xff09; SPfile修改的步驟&#xff1a;a) 修改SPFILE參數control_filesb) 一致性關閉數據庫c) 增加或減少控制文件d) 啟動數據庫使用SPFILEe) 驗證結果 實驗&#xff…

String類的使用 Part2

StringBuilder 類的使用 屬性&#xff1a; namespace StringBuilderTest {class Program{static void Main(string[] args){StringBuilder s new StringBuilder("hello,world!");Console.WriteLine(s);//Length屬性Console.WriteLine("s.Length{0}", s.Le…

JAVA項目怎么不是藍色_解決IDEA創建maven項目時pom.xml沒有變藍的問題

如下所示&#xff1a;選中pom.xml&#xff0c;右鍵點擊add as maven project&#xff0c;稍等片刻后就可以了補充知識&#xff1a;Idea導入maven項目不自動識別pom.xml*Idea導入maven項目不自動識別pom.xml*當在idea中導入maven項目時&#xff0c;不能自動識別pom文件解決方法&…