Java 中的強引用、軟引用、弱引用和虛引用分別是什麼?

Eiffelzero發表於2024-12-11

Java 中的引用型別:強引用、軟引用、弱引用和虛引用

Java 中的引用型別主要分為 強引用軟引用弱引用虛引用,它們對物件的生命週期和垃圾回收(GC)行為產生不同的影響。


1. 強引用(Strong Reference)

定義

強引用是 Java 中最常見的引用型別。透過賦值運算子 = 建立的普通引用即為強引用。

特點

  • 只要強引用存在,垃圾回收器(GC)就不會回收引用指向的物件。
  • 強引用物件通常儲存在堆記憶體中。

示例

public class StrongReferenceExample {
    public static void main(String[] args) {
        Object obj = new Object(); // 強引用
        System.out.println(obj); // 強引用存在,obj 不會被回收
    }
}

2. 軟引用(Soft Reference)

定義

軟引用是一種相對較弱的引用型別,可透過 java.lang.ref.SoftReference 類實現。

特點

  • 軟引用指向的物件在記憶體不足時才會被 GC 回收(適合實現快取)。
  • 軟引用可以延長一些大物件的生命週期,直到 JVM 記憶體不足。

示例

import java.lang.ref.SoftReference;

public class SoftReferenceExample {
    public static void main(String[] args) {
        Object obj = new Object();
        SoftReference<Object> softRef = new SoftReference<>(obj);
        
        obj = null; // 去掉強引用
        System.out.println(softRef.get()); // 軟引用仍然可用
        
        // 在記憶體不足時,softRef 可能會被回收
    }
}

注意

  • 軟引用常用於實現記憶體敏感的快取機制。

3. 弱引用(Weak Reference)

定義

弱引用是一種比軟引用更弱的引用型別,可透過 java.lang.ref.WeakReference 類實現。

特點

  • 只要 GC 發現弱引用物件沒有強引用或軟引用關聯時,立即回收。
  • 通常用於實現規範化對映(如 WeakHashMap)。

示例

import java.lang.ref.WeakReference;

public class WeakReferenceExample {
    public static void main(String[] args) {
        Object obj = new Object();
        WeakReference<Object> weakRef = new WeakReference<>(obj);
        
        obj = null; // 去掉強引用
        System.out.println(weakRef.get()); // 弱引用仍然可用
        
        System.gc(); // 顯式呼叫 GC
        System.out.println(weakRef.get()); // 弱引用可能被回收,返回 null
    }
}

注意

  • 弱引用非常適合使用在快取或動態代理中。

4. 虛引用(Phantom Reference)

定義

虛引用是一種最弱的引用型別,可透過 java.lang.ref.PhantomReference 類實現。

特點

  • 虛引用不會決定物件的生命週期。
  • 主要用於跟蹤物件被回收的時間點。
  • 虛引用必須與引用佇列(ReferenceQueue)一起使用。

示例

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

public class PhantomReferenceExample {
    public static void main(String[] args) {
        Object obj = new Object();
        ReferenceQueue<Object> queue = new ReferenceQueue<>();
        PhantomReference<Object> phantomRef = new PhantomReference<>(obj, queue);
        
        obj = null; // 去掉強引用
        System.gc(); // 顯式呼叫 GC
        
        // 虛引用本身無法透過 get() 方法獲取物件
        System.out.println(phantomRef.get()); // 始終返回 null
    }
}

注意

  • 虛引用常用於清理工作或監控物件的回收狀態。

5. 引用型別的對比

引用型別 描述 對 GC 的影響 適用場景
強引用 預設的引用型別,物件存活取決於引用 GC 永遠不會回收 常規物件引用
軟引用 記憶體不足時回收 記憶體不足時 GC 可能回收 快取實現
弱引用 只要 GC 發現,立即回收 只要無強引用或軟引用時,立即回收 WeakHashMap、動態代理等
虛引用 無法直接訪問物件,僅用於回收跟蹤 GC 回收後加入 ReferenceQueue 清理資源、監控物件回收狀態

6. 總結

  • 強引用:最常見的引用型別,保證物件不被回收。
  • 軟引用:記憶體敏感的引用,適合快取場景。
  • 弱引用:短生命週期的引用,適合規範化對映或動態代理。
  • 虛引用:僅用於監控物件的回收,適合清理或跟蹤任務。

相關文章