Java引用型別解析:掌握強引用、軟引用、弱引用和幻象引用的妙用

架构师老卢發表於2024-03-03
Java引用型別解析:掌握強引用、軟引用、弱引用和幻象引用的妙用

概述:Java中的引用分為強引用、軟引用、弱引用和幻象引用。強引用是最常見的,不會被垃圾回收;軟引用在記憶體不足時才被回收;弱引用在下一次垃圾回收時回收;幻象引用用於檢測物件是否已被回收。它們各自適用於不同場景,幫助開發者更靈活地管理物件生命週期,避免記憶體洩漏。

在Java中,引用是一種機制,用於在進行垃圾回收時確定物件是否可被回收。Java中的引用主要分為強引用、軟引用、弱引用和幻象引用。以下是它們的詳細講解,包括應用場景和注意事項。

1. 強引用(Strong Reference):

強引用是最普通的引用型別。如果一個物件具有強引用,垃圾回收器絕不會回收它,即使記憶體不足。

應用場景:

  • 物件的生命週期需要與引用保持一致。
  • 大多數物件預設是強引用。

注意事項:

  • 可能導致記憶體洩漏,因為強引用的物件只有在顯式地被設定為null時才能被垃圾回收。

例項程式碼:

public class StrongReferenceExample {
    public static void main(String[] args) {
        // 建立強引用
        Object object = new Object();
        
        // object仍然可訪問
        System.out.println(object);
        
        // 設定為null後,object可能被垃圾回收
        object = null;
    }
}

2. 軟引用(Soft Reference):

軟引用在系統即將發生記憶體溢位之前,會被垃圾回收器回收。

應用場景:

  • 對於可有可無的快取資料。

注意事項:

  • 當系統記憶體充足時,軟引用不會被回收,但在記憶體不足時會被垃圾回收。

例項程式碼:

import java.lang.ref.SoftReference;

public class SoftReferenceExample {
    public static void main(String[] args) {
        // 建立軟引用
        SoftReference<Object> softReference = new SoftReference<>(new Object());
        
        // 獲取軟引用物件
        Object object = softReference.get();
        
        // object仍然可訪問
        System.out.println(object);
        
        // 在記憶體不足時,softReference可能被垃圾回收
    }
}

3. 弱引用(Weak Reference):

弱引用在下一次垃圾回收時就會被回收,不考慮記憶體是否充足。

應用場景:

  • 用於實現物件快取,但不希望物件快取在記憶體中太久。

注意事項:

  • 當發生垃圾回收時,弱引用物件會被立即回收。

例項程式碼:

import java.lang.ref.WeakReference;

public class WeakReferenceExample {
    public static void main(String[] args) {
        // 建立弱引用
        WeakReference<Object> weakReference = new WeakReference<>(new Object());
        
        // 獲取弱引用物件
        Object object = weakReference.get();
        
        // object仍然可訪問
        
        // 強制觸發垃圾回收
        System.gc();
        
        // 在垃圾回收後,weakReference可能被回收
    }
}

4. 幻象引用(Phantom Reference):

幻象引用用於檢測物件是否已經從記憶體中刪除。

應用場景:

  • 通常與ReferenceQueue一起使用,用於在物件被垃圾回收前執行一些清理操作。

注意事項:

  • 幻象引用的get方法始終返回null。
  • 必須使用ReferenceQueue來配合使用,以獲知物件何時被回收。

例項程式碼:

import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;

public class PhantomReferenceExample {
    public static void main(String[] args) {
        ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
        
        // 建立幻象引用
        PhantomReference<Object> phantomReference = new PhantomReference<>(new Object(), referenceQueue);
        
        // 獲取幻象引用物件,始終返回null
        Object object = phantomReference.get();
        
        // 在垃圾回收後,phantomReference會被放入referenceQueue
        System.gc();
        
        // 從referenceQueue中獲取被回收的引用
        PhantomReference<Object> collectedReference = (PhantomReference<Object>) referenceQueue.poll();
    }
}

透過使用這些引用型別,可以更靈活地管理物件的生命週期,同時避免記憶體洩漏和提高系統效能。

相關文章