概述: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();
}
}
透過使用這些引用型別,可以更靈活地管理物件的生命週期,同時避免記憶體洩漏和提高系統效能。