在java中,对象引用主要分为五种类型:强引用、软引用、
弱引用、虚引用、终结期引用。
1. 强引用
最常见的引用类型,默认创建的引用都是强引用。
Object obj = new Object(); // 强引用
特点:
- 只要强引用存在,对象永远不会被回收
- 内存不足时抛出
OutOfMemoryError - 使用场景:普通对象创建
回收条件:
obj = null; // 显式解除引用
2.软引用
// 创建软引用
SoftReference<byte[]> softRef = new SoftReference<>(new byte[10*1024*1024]); // 10MB
特点:
- 内存充足时不会被回收
- 内存不足时可能被回收
- 使用场景:图片缓存、网页缓存
3.弱引用
// 创建弱引用
WeakReference<Object> weakRef = new WeakReference<>(new Object());
// 获取对象
Object obj = weakRef.get();
if (obj != null) {
System.out.println("弱引用对象存在");
}
// 强制垃圾回收
System.gc();
// 再次检查
if (weakRef.get() == null) {
System.out.println("对象已被回收");
}
特点:
- 下一次垃圾回收时立即回收(无其他引用)
- 不会阻止垃圾回收
- 使用场景:临时对象映射、监控对象状态
虚引用和终结器引用在常规开发中是不会使用的。
4.虚引用
虚引用也被称为幽灵引用或者幻影引用,它不会影响对象的生命周期,也无法通过虚引用获取到对象实例。虚引用的主要作用是在对象被垃圾回收时收到一个系统通知。创建虚引用时必须关联一个引用队列(ReferenceQueue),当虚引用引用的对象被垃圾回收后,该虚引用会被加入到关联的引用队列中。
使用场景
虚引用主要用于在对象被回收时执行一些额外的清理操作,比如管理直接内存。直接内存不受 Java 堆内存管理,需要手动释放,使用虚引用可以在对象被回收时释放对应的直接内存资源。
示例代码
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> referenceQueue = new ReferenceQueue<>();
// 创建虚引用,关联对象和引用队列
PhantomReference<Object> phantomReference = new PhantomReference<>(obj, referenceQueue);
// 断开强引用
obj = null;
// 建议 JVM 进行垃圾回收
System.gc();
try {
// 等待一段时间,让垃圾回收有机会执行
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 检查引用队列中是否有虚引用
if (referenceQueue.poll() != null) {
System.out.println("对象已被垃圾回收,虚引用已加入引用队列");
} else {
System.out.println("对象尚未被垃圾回收");
}
}
}
特点:
- 无法通过
get()获取对象 - 对象被回收时收到通知
- 使用场景:直接内存清理、资源释放
5.终结器引用
class ResourceHolder {
private byte[] data = new byte[1024*1024]; // 1MB
@Override
protected void finalize() throws Throwable {
try {
System.out.println("执行 finalize() 清理资源");
} finally {
super.finalize();
}
}
}
// 使用
new ResourceHolder();
System.gc();
特点:
- 对象被回收前会调用
finalize()方法 - 执行时间不确定
- 使用场景:传统资源清理(已被
try-with-resources取代)
try-with-resources
try (
InputStream in = new FileInputStream("input.txt");
OutputStream out = new FileOutputStream("output.txt")
) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = in.read(buffer)) != -1) {
out.write(buffer, 0, bytesRead);
}
} // 自动关闭 in 和 out

579

被折叠的 条评论
为什么被折叠?



