欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java中的Reference和引用類型實例精講

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

簡介

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

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

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

強引用Strong Reference

java中的引用默認就是強引用,任何一個對象的賦值操作就產生了對這個對象的強引用。

我們看一個例子:

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

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

強引用的特性是只要有強引用存在,被引用的對象就不會被垃圾回收。

軟引用Soft Reference

軟引用在java中有個專門的SoftReference類型,軟引用的意思是只有在內存不足的情況下,被引用的對象才會被回收。

先看下SoftReference的定義:

public class SoftReference<T> extends Reference<T>

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

public SoftReference(T referent)

和:

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

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

我們舉個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());
    }

輸出結果:

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

可以看到在內存充足的情況下,SoftReference引用的對象是不會被回收的。

弱引用weak Reference

weakReference和softReference很類似,不同的是weekReference引用的對象只要垃圾回收執(zhí)行,就會被回收,而不管是否內存不足。

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

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

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

我們看下弱引用的例子:

@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());
    }

輸出結果:

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

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

虛引用PhantomReference

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

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

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

看一個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);
    }
}

運行結果:

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是有值的。

因為PhantomReference引用的是需要被垃圾回收的對象,所以在類的定義中,get一直都是返回null:

public T get() {
        return null;
    }

Reference和ReferenceQueue

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

Reference是一個抽象類,每個Reference都有一個指向的對象,在Reference中有5個非常重要的屬性: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;

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

先用一張圖來對Reference有個整體的概念:

referent就是Reference實際引用的對象。

通過next屬性,可以構建ReferenceQueue。

通過discovered屬性,可以構建Discovered List。

通過pending屬性,可以構建Pending List。

四大狀態(tài)

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

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

因為Reference有兩個構造函數(shù),一個帶ReferenceQueue,一個不帶。

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

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

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

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

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

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

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

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

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

這就是Reference的一個完整的生命周期。

三個Queue/List

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

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

pending List就是待入ReferenceQueue的list。

discovered List這個有點特別,在Pending狀態(tài)時候,discovered List就等于pending List。

在Active狀態(tài)的時候,discovered List實際上維持的是一個引用鏈。通過這個引用鏈,我們可以獲得引用的鏈式結構,當某個Reference狀態(tài)不再是Active狀態(tài)時,需要將這個Reference從discovered List中刪除。

WeakHashMap

最后講一下WeakHashMap,WeakHashMap跟WeakReference有點類似,在WeakHashMap如果key不再被使用,被賦值為null的時候,該key對應的Entry會自動從WeakHashMap中刪除。

我們舉個例子:

@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);
    }

輸出結果:

[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只有一個Entry了。

總結

本文講解了4個java中的引用類型,并深入探討了Reference的內部機制。

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

更多關于java Reference引用類型的資料請關注腳本之家其它相關文章!

相關文章

  • 如何通過java實現(xiàn)highcharts導出圖片至excel

    如何通過java實現(xiàn)highcharts導出圖片至excel

    這篇文章主要介紹了如何通過java實現(xiàn)highcharts導出圖片至excel。文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,下面我們就來一起學習一下吧
    2019-06-06
  • Dubbo Consumer引用服務示例代碼詳解

    Dubbo Consumer引用服務示例代碼詳解

    dubbo中引用遠程服務有兩種方式:服務直連(不經過注冊中心)、基于注冊中心引用服務,在實際線上環(huán)境中我們基本上使用的都是基于注冊中心引用服務的方式,下面我們就圍繞該方式講解分析
    2023-03-03
  • Java 獲取指定日期的實現(xiàn)方法總結

    Java 獲取指定日期的實現(xiàn)方法總結

    以下是對Java中獲取指定日期的實現(xiàn)方法進行了歸納總結,需要的朋友可以參考下
    2013-07-07
  • Spring?MVC數(shù)據綁定方式

    Spring?MVC數(shù)據綁定方式

    這篇文章主要介紹了Spring?MVC數(shù)據綁定方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • Java指令重排序在多線程環(huán)境下的處理方法

    Java指令重排序在多線程環(huán)境下的處理方法

    指令重排在單線程環(huán)境下有利于提高程序的執(zhí)行效率,不會對程序產生負面影響,本文對多線程指令重排問題進行復原,并針對指令重排給出相應的解決方案,需要的朋友參考下吧
    2022-04-04
  • Java網絡編程基礎篇之單向通信

    Java網絡編程基礎篇之單向通信

    這篇文章主要介紹了Java網絡編程里通過套接字實現(xiàn)單向通信的方法及相關實例,屬于網絡編程入門程序,雖然簡單,但具有一定參考價值,需要的朋友可以參考下。
    2017-09-09
  • SpringMvc之HandlerMapping詳解

    SpringMvc之HandlerMapping詳解

    這篇文章主要介紹了SpringMvc之HandlerMapping詳解,Handler可以理解為具體干活的,也就是我們的業(yè)務處理邏輯,Handler最終是要通過url 來訪問到,這樣url 與Handler之間就有一個映射關系了,需要的朋友可以參考下
    2023-08-08
  • Spring SmartLifecycle:如何精準控制Bean的生命周期

    Spring SmartLifecycle:如何精準控制Bean的生命周期

    這篇文章主要介紹了Spring SmartLifecycle:如何精準控制Bean的生命周期問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-03-03
  • SpringBoot 中 AutoConfiguration的使用方法

    SpringBoot 中 AutoConfiguration的使用方法

    這篇文章主要介紹了SpringBoot 中 AutoConfiguration的使用方法,本文通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-04-04
  • java發(fā)送heartbeat心跳包(byte轉16進制)

    java發(fā)送heartbeat心跳包(byte轉16進制)

    這篇文章主要介紹了java發(fā)送heartbeat心跳包(byte轉16進制),需要的朋友可以參考下
    2014-05-05

最新評論