面试题答案
一键面试对象的引用类型
- 强引用(Strong Reference):这是Java中最常见的引用类型。当一个对象具有强引用时,垃圾回收器绝不会回收它,只有当所有指向该对象的强引用都被断开时,对象才会被垃圾回收器回收。
- 软引用(Soft Reference):软引用指向的对象在系统将要发生内存溢出之前,会被垃圾回收器回收。如果还有足够的内存,软引用对象不会被回收。常用于实现对内存敏感的缓存。
- 弱引用(Weak Reference):弱引用指向的对象只要垃圾回收器扫描到了,不管当前内存空间是否足够,都会被回收。
- 虚引用(Phantom Reference):虚引用也称为幽灵引用或者幻影引用,它是最弱的一种引用关系。一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。为对象设置虚引用关联的唯一目的就是能在这个对象被收集器回收时收到一个系统通知。
对内存占用和垃圾回收机制的影响及举例
- 强引用
- 影响:只要对象有强引用,就会一直占用内存,不会被垃圾回收。
- 示例:
Object strongRef = new Object();
这里strongRef
是一个强引用,只要strongRef
还指向这个Object
实例,该实例就不会被回收。如果后续代码执行strongRef = null;
,断开了强引用,这个Object
实例才有可能被垃圾回收。
2. 软引用
- 影响:软引用对象在内存不足时会被回收,有助于在内存紧张时释放部分不那么重要的对象所占用的内存。
- 示例:
import java.lang.ref.SoftReference;
public class SoftReferenceExample {
public static void main(String[] args) {
SoftReference<String> softRef = new SoftReference<>(new String("soft reference object"));
String obj = softRef.get();
if (obj != null) {
System.out.println("Object retrieved: " + obj);
} else {
System.out.println("Object has been garbage collected.");
}
}
}
如果内存充足,softRef.get()
能获取到对象;当内存紧张时,该对象可能被回收,softRef.get()
会返回null
。
3. 弱引用
- 影响:弱引用对象随时可能被垃圾回收,即使内存充足也可能被回收,所以它不能保证对象一定存在。
- 示例:
import java.lang.ref.WeakReference;
public class WeakReferenceExample {
public static void main(String[] args) {
WeakReference<String> weakRef = new WeakReference<>(new String("weak reference object"));
String obj = weakRef.get();
if (obj != null) {
System.out.println("Object retrieved: " + obj);
} else {
System.out.println("Object has been garbage collected.");
}
// 触发垃圾回收
System.gc();
obj = weakRef.get();
if (obj != null) {
System.out.println("Object retrieved after gc: " + obj);
} else {
System.out.println("Object has been garbage collected after gc.");
}
}
}
运行代码时,即使内存充足,在调用System.gc()
后,弱引用指向的对象很可能被回收,weakRef.get()
可能返回null
。
4. 虚引用
- 影响:虚引用对对象的生命周期没有影响,主要用于在对象被回收时收到通知。
- 示例:
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
public class PhantomReferenceExample {
public static void main(String[] args) {
ReferenceQueue<String> queue = new ReferenceQueue<>();
String str = new String("phantom reference object");
PhantomReference<String> phantomRef = new PhantomReference<>(str, queue);
// 不能通过虚引用获取对象实例
String obj = phantomRef.get();
if (obj != null) {
System.out.println("Object retrieved: " + obj);
} else {
System.out.println("Can't retrieve object through phantom reference.");
}
// 断开强引用
str = null;
// 触发垃圾回收
System.gc();
try {
// 检查引用队列中是否有虚引用对象被加入
java.lang.ref.Reference<?> ref = queue.remove();
if (ref != null) {
System.out.println("Object has been garbage collected and phantom reference enqueued.");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
当str
的强引用断开并触发垃圾回收后,虚引用phantomRef
会被放入引用队列queue
中,通过queue.remove()
可以获取到这个虚引用,从而得知对象已被回收。