最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

java中的Reference和引用類型實(shí)例精講

 更新時(shí)間:2023年09月15日 09:29:06   作者:flydean  
這篇文章主要為大家介紹了java中的Reference和引用類型示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

簡介

java中有值類型也有引用類型,引用類型一般是針對(duì)于java中對(duì)象來說的,今天介紹一下java中的引用類型。java為引用類型專門定義了一個(gè)類叫做Reference。Reference是跟java垃圾回收機(jī)制息息相關(guān)的類,通過探討Reference的實(shí)現(xiàn)可以更加深入的理解java的垃圾回收是怎么工作的。

本文先從java中的四種引用類型開始,一步一步揭開Reference的面紗。

java中的四種引用類型分別是:強(qiáng)引用,軟引用,弱引用和虛引用。

強(qiáng)引用Strong Reference

java中的引用默認(rèn)就是強(qiáng)引用,任何一個(gè)對(duì)象的賦值操作就產(chǎn)生了對(duì)這個(gè)對(duì)象的強(qiáng)引用。

我們看一個(gè)例子:

public class StrongReferenceUsage {
    @Test
    public void stringReference(){
        Object obj = new Object();
    }
}

上面我們new了一個(gè)Object對(duì)象,并將其賦值給obj,這個(gè)obj就是new Object()的強(qiáng)引用。

強(qiáng)引用的特性是只要有強(qiáng)引用存在,被引用的對(duì)象就不會(huì)被垃圾回收。

軟引用Soft Reference

軟引用在java中有個(gè)專門的SoftReference類型,軟引用的意思是只有在內(nèi)存不足的情況下,被引用的對(duì)象才會(huì)被回收。

先看下SoftReference的定義:

public class SoftReference<T> extends Reference<T>

SoftReference繼承自Reference。它有兩種構(gòu)造函數(shù):

public SoftReference(T referent)

和:

public SoftReference(T referent, ReferenceQueue<? super T> q)

第一個(gè)參數(shù)很好理解,就是軟引用的對(duì)象,第二個(gè)參數(shù)叫做ReferenceQueue,是用來存儲(chǔ)封裝的待回收Reference對(duì)象的,ReferenceQueue中的對(duì)象是由Reference類中的ReferenceHandler內(nèi)部類進(jìn)行處理的。

我們舉個(gè)SoftReference的例子:

@Test
    public void softReference(){
        Object obj = new Object();
        SoftReference<Object> soft = new SoftReference<>(obj);
        obj = null;
        log.info("{}",soft.get());
        System.gc();
        log.info("{}",soft.get());
    }

輸出結(jié)果:

22:50:43.733 [main] INFO com.flydean.SoftReferenceUsage - java.lang.Object@71bc1ae4
22:50:43.749 [main] INFO com.flydean.SoftReferenceUsage - java.lang.Object@71bc1ae4

可以看到在內(nèi)存充足的情況下,SoftReference引用的對(duì)象是不會(huì)被回收的。

弱引用weak Reference

weakReference和softReference很類似,不同的是weekReference引用的對(duì)象只要垃圾回收?qǐng)?zhí)行,就會(huì)被回收,而不管是否內(nèi)存不足。

同樣的WeakReference也有兩個(gè)構(gòu)造函數(shù):

public WeakReference(T referent);
 public WeakReference(T referent, ReferenceQueue<? super T> q);

含義和SoftReference一致,這里就不再重復(fù)表述了。

我們看下弱引用的例子:

@Test
    public void weakReference() throws InterruptedException {
        Object obj = new Object();
        WeakReference<Object> weak = new WeakReference<>(obj);
        obj = null;
        log.info("{}",weak.get());
        System.gc();
        log.info("{}",weak.get());
    }

輸出結(jié)果:

22:58:02.019 [main] INFO com.flydean.WeakReferenceUsage - java.lang.Object@71bc1ae4
22:58:02.047 [main] INFO com.flydean.WeakReferenceUsage - null

我們看到gc過后,弱引用的對(duì)象被回收掉了。

虛引用PhantomReference

PhantomReference的作用是跟蹤垃圾回收器收集對(duì)象的活動(dòng),在GC的過程中,如果發(fā)現(xiàn)有PhantomReference,GC則會(huì)將引用放到ReferenceQueue中,由程序員自己處理,當(dāng)程序員調(diào)用ReferenceQueue.pull()方法,將引用出ReferenceQueue移除之后,Reference對(duì)象會(huì)變成Inactive狀態(tài),意味著被引用的對(duì)象可以被回收了。

和SoftReference和WeakReference不同的是,PhantomReference只有一個(gè)構(gòu)造函數(shù),必須傳入ReferenceQueue:

public PhantomReference(T referent, ReferenceQueue<? super T> q)

看一個(gè)PhantomReference的例子:

@Slf4j
public class PhantomReferenceUsage {
    @Test
    public void usePhantomReference(){
        ReferenceQueue<Object> rq = new ReferenceQueue<>();
        Object obj = new Object();
        PhantomReference<Object> phantomReference = new PhantomReference<>(obj,rq);
        obj = null;
        log.info("{}",phantomReference.get());
        System.gc();
        Reference<Object> r = (Reference<Object>)rq.poll();
        log.info("{}",r);
    }
}

運(yùn)行結(jié)果:

07:06:46.336 [main] INFO com.flydean.PhantomReferenceUsage - null
07:06:46.353 [main] INFO com.flydean.PhantomReferenceUsage - java.lang.ref.PhantomReference@136432db

我們看到get的值是null,而GC過后,poll是有值的。

因?yàn)镻hantomReference引用的是需要被垃圾回收的對(duì)象,所以在類的定義中,get一直都是返回null:

public T get() {
        return null;
    }

Reference和ReferenceQueue

講完上面的四種引用,接下來我們談一下他們的父類Reference和ReferenceQueue的作用。

Reference是一個(gè)抽象類,每個(gè)Reference都有一個(gè)指向的對(duì)象,在Reference中有5個(gè)非常重要的屬性:referent,next,discovered,pending,queue。

private T referent;         /* Treated specially by GC */
volatile ReferenceQueue<? super T> queue;
Reference next;
transient private Reference<T> discovered;  /* used by VM */
private static Reference<Object> pending = null;

每個(gè)Reference都可以看成是一個(gè)節(jié)點(diǎn),多個(gè)Reference通過next,discovered和pending這三個(gè)屬性進(jìn)行關(guān)聯(lián)。

先用一張圖來對(duì)Reference有個(gè)整體的概念:

referent就是Reference實(shí)際引用的對(duì)象。

通過next屬性,可以構(gòu)建ReferenceQueue。

通過discovered屬性,可以構(gòu)建Discovered List。

通過pending屬性,可以構(gòu)建Pending List。

四大狀態(tài)

在講這三個(gè)Queue/List之前,我們先講一下Reference的四個(gè)狀態(tài):

從上面的圖中,我們可以看到一個(gè)Reference可以有四個(gè)狀態(tài)。

因?yàn)镽eference有兩個(gè)構(gòu)造函數(shù),一個(gè)帶ReferenceQueue,一個(gè)不帶。

Reference(T referent) {
        this(referent, null);
    }
    Reference(T referent, ReferenceQueue<? super T> queue) {
        this.referent = referent;
        this.queue = (queue == null) ? ReferenceQueue.NULL : queue;
    }

對(duì)于帶ReferenceQueue的Reference,GC會(huì)把要回收對(duì)象的Reference放到ReferenceQueue中,后續(xù)該Reference需要程序員自己處理(調(diào)用poll方法)。

不帶ReferenceQueue的Reference,由GC自己處理,待回收的對(duì)象其Reference狀態(tài)會(huì)變成Inactive。

創(chuàng)建好了Reference,就進(jìn)入active狀態(tài)。

active狀態(tài)下,如果引用對(duì)象的可到達(dá)狀態(tài)發(fā)送變化就會(huì)轉(zhuǎn)變成Inactive或Pending狀態(tài)。

Inactive狀態(tài)很好理解,到達(dá)Inactive狀態(tài)的Reference狀態(tài)不能被改變,會(huì)等待GC回收。

Pending狀態(tài)代表等待入Queue,Reference內(nèi)部有個(gè)ReferenceHandler,會(huì)調(diào)用enqueue方法,將Pending對(duì)象入到Queue中。

入Queue的對(duì)象,其狀態(tài)就變成了Enqueued。

Enqueued狀態(tài)的對(duì)象,如果調(diào)用poll方法從ReferenceQueue拿出,則該Reference的狀態(tài)就變成了Inactive,等待GC的回收。

這就是Reference的一個(gè)完整的生命周期。

三個(gè)Queue/List

有了上面四個(gè)狀態(tài)的概念,我們接下來講三個(gè)Queue/List:ReferenceQueue,discovered List和pending List。

ReferenceQueue在講狀態(tài)的時(shí)候已經(jīng)講過了,它本質(zhì)是由Reference中的next連接而成的。用來存儲(chǔ)GC待回收的對(duì)象。

pending List就是待入ReferenceQueue的list。

discovered List這個(gè)有點(diǎn)特別,在Pending狀態(tài)時(shí)候,discovered List就等于pending List。

在Active狀態(tài)的時(shí)候,discovered List實(shí)際上維持的是一個(gè)引用鏈。通過這個(gè)引用鏈,我們可以獲得引用的鏈?zhǔn)浇Y(jié)構(gòu),當(dāng)某個(gè)Reference狀態(tài)不再是Active狀態(tài)時(shí),需要將這個(gè)Reference從discovered List中刪除。

WeakHashMap

最后講一下WeakHashMap,WeakHashMap跟WeakReference有點(diǎn)類似,在WeakHashMap如果key不再被使用,被賦值為null的時(shí)候,該key對(duì)應(yīng)的Entry會(huì)自動(dòng)從WeakHashMap中刪除。

我們舉個(gè)例子:

@Test
    public void useWeakHashMap(){
        WeakHashMap<Object, Object> map = new WeakHashMap<>();
        Object key1= new Object();
        Object value1= new Object();
        Object key2= new Object();
        Object value2= new Object();
        map.put(key1, value1);
        map.put(key2, value2);
        log.info("{}",map);
        key1 = null;
        System.gc();
        log.info("{}",map);
    }

輸出結(jié)果:

[main] INFO com.flydean.WeakHashMapUsage - {java.lang.Object@14899482=java.lang.Object@2437c6dc, java.lang.Object@11028347=java.lang.Object@1f89ab83}
[main] INFO com.flydean.WeakHashMapUsage - {java.lang.Object@14899482=java.lang.Object@2437c6dc}

可以看到gc過后,WeakHashMap只有一個(gè)Entry了。

總結(jié)

本文講解了4個(gè)java中的引用類型,并深入探討了Reference的內(nèi)部機(jī)制。

本文的例子https://github.com/ddean2009/learn-java-collections

更多關(guān)于java Reference引用類型的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • springboot+chatgpt+chatUI Pro開發(fā)智能聊天工具的實(shí)踐

    springboot+chatgpt+chatUI Pro開發(fā)智能聊天工具的實(shí)踐

    本文主要介紹了springboot+chatgpt+chatUI Pro開發(fā)智能聊天工具的實(shí)踐,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • Java 進(jìn)制轉(zhuǎn)換的方法

    Java 進(jìn)制轉(zhuǎn)換的方法

    這篇文章介紹了Java 進(jìn)制轉(zhuǎn)換的方法,有需要的朋友可以參考一下
    2013-09-09
  • JDK安裝方法和Linux常見設(shè)置詳細(xì)版教程

    JDK安裝方法和Linux常見設(shè)置詳細(xì)版教程

    這篇文章主要給大家介紹了關(guān)于JDK安裝方法和Linux常見設(shè)置的相關(guān)資料,文章詳細(xì)介紹了如何在Linux系統(tǒng)中設(shè)置靜態(tài)IP、用戶名和主機(jī)名,配置防火墻,安裝JDK以及如何創(chuàng)建系統(tǒng)快照,需要的朋友可以參考下
    2024-11-11
  • SpringBoot上傳下載文件+oss實(shí)例

    SpringBoot上傳下載文件+oss實(shí)例

    這篇文章主要介紹了SpringBoot上傳下載文件+oss實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-04-04
  • Spring?Boot項(xiàng)目Jar包加密實(shí)戰(zhàn)教程

    Spring?Boot項(xiàng)目Jar包加密實(shí)戰(zhàn)教程

    本文詳細(xì)介紹了如何在Spring?Boot項(xiàng)目中實(shí)現(xiàn)Jar包加密,我們首先了解了Jar包加密的基本概念和作用,然后學(xué)習(xí)了如何使用Spring?Boot的Jar工具和第三方庫來實(shí)現(xiàn)Jar包的加密和解密,感興趣的朋友一起看看吧
    2024-02-02
  • Java?IO?API實(shí)現(xiàn)獲取路徑信息并去除冗余信息

    Java?IO?API實(shí)現(xiàn)獲取路徑信息并去除冗余信息

    這篇文章主要為大家詳細(xì)介紹了Java?IO?API實(shí)現(xiàn)獲取路徑信息并去除冗余信息,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2026-03-03
  • JVM的7種垃圾回收器(小結(jié))

    JVM的7種垃圾回收器(小結(jié))

    這篇文章主要介紹了JVM的7種垃圾回收器(小結(jié)),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • SpringBoot自動(dòng)裝配的原理與使用

    SpringBoot自動(dòng)裝配的原理與使用

    在現(xiàn)代的軟件開發(fā)中,依賴管理是一個(gè)關(guān)鍵的任務(wù),隨著應(yīng)用程序規(guī)模的增長,手動(dòng)管理對(duì)象之間的依賴關(guān)系變得越來越復(fù)雜,為了解決這個(gè)問題,Spring Boot提供了一種強(qiáng)大的功能,即自動(dòng)裝配,感興趣想要詳細(xì)了解可以參考下文
    2023-05-05
  • Java線程編程中Thread類的基礎(chǔ)學(xué)習(xí)教程

    Java線程編程中Thread類的基礎(chǔ)學(xué)習(xí)教程

    這篇文章主要介紹了Java線程編程中Thread類的基礎(chǔ)學(xué)習(xí)教程,Thread類包含諸多操作線程的方法,非常重要,需要的朋友可以參考下
    2015-12-12
  • Java基礎(chǔ)之this關(guān)鍵字的使用

    Java基礎(chǔ)之this關(guān)鍵字的使用

    今天給大家?guī)淼氖顷P(guān)于Java基礎(chǔ)的相關(guān)知識(shí),文章圍繞著this關(guān)鍵字的使用展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06

最新評(píng)論

金寨县| 阿巴嘎旗| 湛江市| 鄂尔多斯市| 龙岩市| 乐陵市| 鄂托克前旗| 兴文县| 罗城| 瑞丽市| 贺兰县| 濮阳市| 万年县| 南阳市| 务川| 公安县| 襄城县| 龙江县| 察雅县| 外汇| 延吉市| 汶川县| 长武县| 荥阳市| 铁力市| 盘山县| 邯郸县| 长兴县| 许昌市| 平安县| 邳州市| 镇康县| 永靖县| 万全县| 商洛市| 潼关县| 肇东市| 永川市| 峨边| 福鼎市| 原平市|