强软弱虚,Java中常见的四种引用。
1.强引用
强引用(Strong Reference)是最常见的引用类型,在Java中使用最广泛。
当我们使用一个对象的强引用时,JVM会确保该对象不会被垃圾回收器回收,只有当强引用被显式地释放(赋值为null)或不再被使用时,垃圾回收器才会回收该对象。
强引用的特点如下:
- 强引用可以直接访问对象并保持对其的引用关系,对象不会被回收。
- 强引用可以作为对象的唯一引用,当没有任何强引用指向一个对象时,该对象就变成了可回收的垃圾。
- 强引用可以通过赋值为null来释放对对象的引用,使得对象变为垃圾,等待下一次垃圾回收。
示例代码如下:
public class StrongReferenceExample {
public static void main(String[] args) {
// 创建一个字符串对象并创建强引用
String data = "Hello World";
// 输出强引用对象的值
System.out.println("Strong reference value: " + data);
// 释放强引用
data = null;
// 再次输出强引用对象的值(此时为null)
System.out.println("Strong reference value after release: " + data);
// 手动触发垃圾回收
System.gc();
}
}
在上述代码中,我们创建了一个字符串对象,并使用强引用对其进行引用。
在释放强引用后,对象变为可回收的垃圾。
通过手动触发垃圾回收,可以看到输出结果中没有任何与强引用对象相关的信息。
这说明强引用不会被垃圾回收器回收,只有当没有任何强引用指向对象时,对象才会被回收。
2.软引用
软引用(Soft Reference)是Java中一种相对较弱的引用类型。
与强引用不同,当内存不足时,垃圾回收器可能会回收被软引用关联的对象,但不保证一定回收。
软引用通常用于实现内存敏感的高速缓存或对象缓存等场景,当系统内存不足时,可以优先回收这部分对象,以释放内存空间。
软引用的特点如下:
- 软引用可以访问对象并保持对其的引用关系,但允许被垃圾回收器回收。
- 当内存不足时,垃圾回收器可能会回收被软引用关联的对象,以释放内存空间。
- 软引用适合用于实现内存敏感的高速缓存或对象缓存等场景,可以在内存紧张时回收一部分对象,避免内存溢出。
代码如下:
import java.lang.ref.SoftReference;
public class SoftReferenceExample {
public static void main(String[] args) {
// 创建一个字符串对象并创建软引用
SoftReference<String> softRef = new SoftReference<>("Hello World");
// 从软引用中获取对象
String data = softRef.get();
// 输出软引用对象的值
System.out.println("Soft reference value: " + data);
// 释放软引用
softRef.clear();
// 再次从软引用中获取对象(此时为null)
data = softRef.get();
// 输出软引用对象的值(此时为null)
System.out.println("Soft reference value after release: " + data);
// 手动触发垃圾回收
System.gc();
}
}
在上述代码中,我们创建了一个字符串对象,并使用软引用对其进行引用。
在释放软引用后,对象变为可回收的垃圾。
通过手动触发垃圾回收,可以看到输出结果中没有任何与软引用对象相关的信息。
这说明软引用可以被垃圾回收器回收,但不是一定会回收,它的回收行为取决于内存的使用情况。
3. 弱引用
弱引用(Weak Reference)是Java中一种比软引用更弱的引用类型。
与软引用不同,弱引用在垃圾回收时更容易被回收。
当垃圾回收器扫描到只有弱引用关联的对象时,无论内存是否充足,都会立即回收该对象。
弱引用的特点如下:
- 弱引用可以访问对象并保持对其的引用关系,但在垃圾回收时更容易被回收。
- 当垃圾回收器扫描到只有弱引用关联的对象时,无论内存是否充足,都会立即回收该对象。
- 弱引用通常用于实现对象缓存,当对象不再被强引用引用时,可以立即回收,避免内存溢出。
示例代码如下:
import java.lang.ref.WeakReference;
public class WeakReferenceExample {
public static void main(String[] args) {
// 创建一个字符串对象并创建弱引用
WeakReference<String> weakRef = new WeakReference<>("Hello World");
// 从弱引用中获取对象
String data = weakRef.get();
// 输出弱引用对象的值
System.out.println("Weak reference value: " + data);
// 释放弱引用
weakRef.clear();
// 再次从弱引用中获取对象(此时为null)
data = weakRef.get();
// 输出弱引用对象的值(此时为null)
System.out.println("Weak reference value after release: " + data);
// 手动触发垃圾回收
System.gc();
}
}
在上述代码中,我们创建了一个字符串对象,并使用弱引用对其进行引用。
在释放弱引用后,对象变为可回收的垃圾。
通过手动触发垃圾回收,可以看到输出结果中没有任何与弱引用对象相关的信息。
这说明弱引用在垃圾回收时更容易被回收,即使内存充足,垃圾回收器也会立即回收弱引用关联的对象。
4.虚引用
虚引用(Phantom Reference)是Java中最弱的引用类型,也是最少被使用的一种引用类型。
与弱引用和软引用不同,虚引用的存在几乎没有实际意义,其主要作用是在对象被回收时收到一个系统通知。
虚引用的特点如下:
- 虚引用不能通过get()方法获取引用的对象,而且始终返回null。
- 虚引用主要用于跟踪对象被垃圾回收的状态,当对象即将被回收时,虚引用会收到一个系统通知。
- 虚引用必须和引用队列(ReferenceQueue)一起使用,用于接收对象被回收的通知。
由于虚引用并不直接与对象关联,所以无法通过虚引用来获取对象的引用或访问对象的属性或方法。
它的主要作用是在对象被回收之前接收到一个通知,可以在对象被回收时进行一些必要的清理操作或记录日志等操作。
示例代码如下:
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
public class PhantomReferenceExample {
public static void main(String[] args) {
Object referent = new Object();
ReferenceQueue<Object> queue = new ReferenceQueue<>();
PhantomReference<Object> phantomRef = new PhantomReference<>(referent, queue);
// 输出虚引用对象
System.out.println("Phantom reference: " + phantomRef);
// 从引用队列中获取已被回收的虚引用
ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
PhantomReference<Object> phantomReference = new PhantomReference<>(new Object(), referenceQueue);
// 输出虚引用对象
System.out.println("Phantom reference from reference queue: " + referenceQueue.poll());
// 手动触发垃圾回收
System.gc();
// 从引用队列中获取已被回收的虚引用
System.out.println("Phantom reference from reference queue: " + referenceQueue.poll());
}
}
在上述代码中,我们创建了一个虚引用对象并输出了该引用对象的信息。
然后,我们手动触发了垃圾回收,并尝试从引用队列中获取已被回收的虚引用对象。
可以看到,虚引用在输出结果中始终为null,说明无法通过虚引用获取对象或引用的信息。
同时,从引用队列中获取的虚引用对象也为null,说明虚引用被回收时会被放入引用队列中。
5.总结
通过上述4个例子和代码,应该对这4个概念掌握了。
这下就算面试官在问,也能手撕面试官了。
ok,我已讲完。