1. 什么是引用?
问题:什么是引用?Java中的引用是如何工作的?
答案:
- 引用 是对象的句柄,用于访问堆内存中的对象。
- 在Java中,引用变量实际上存储的是对象的地址,而不是对象本身。
- 通过引用,可以访问对象的属性和方法。
2. Java中的引用类型有哪些?
问题:Java中有哪几种引用类型?
答案:
- 强引用(Strong Reference) :最常见的引用类型,如
Object obj = new Object()
。只要强引用存在,垃圾回收器就不会回收被引用的对象。 - 软引用(Soft Reference) :通过
SoftReference
类实现。在内存不足时,垃圾回收器会回收软引用指向的对象。 - 弱引用(Weak Reference) :通过
WeakReference
类实现。垃圾回收器在每次垃圾回收时都会回收弱引用指向的对象。 - 虚引用(Phantom Reference) :通过
PhantomReference
类实现。虚引用不会影响对象的生命周期,主要用于在对象被垃圾回收时收到通知。
3. 强引用和软引用有什么区别?
问题:强引用和软引用有什么区别?
答案:
- 强引用 :只要强引用存在,垃圾回收器就不会回收被引用的对象。即使内存不足,也不会回收强引用的对象,可能会导致
OutOfMemoryError
。 - 软引用:在内存不足时,垃圾回收器会回收软引用指向的对象。软引用通常用于实现内存敏感的缓存。
4. 什么是弱引用?它的应用场景是什么?
问题:什么是弱引用?它的应用场景是什么?
答案:
- 弱引用 :通过
WeakReference
类实现。垃圾回收器在每次垃圾回收时都会回收弱引用指向的对象。 - 应用场景 :
- 缓存:用于实现内存敏感的缓存,当内存不足时,可以自动释放缓存对象。
- 监听器:在事件处理中,为了避免内存泄漏,可以使用弱引用来存储监听器。
5. 什么是虚引用?它的应用场景是什么?
问题:什么是虚引用?它的应用场景是什么?
答案:
- 虚引用 :通过
PhantomReference
类实现。虚引用不会影响对象的生命周期,主要用于在对象被垃圾回收时收到通知。 - 应用场景 :
- 资源清理:在对象被垃圾回收时,执行一些资源清理工作,如关闭文件句柄、释放资源等。
6. 如何判断一个对象是否被垃圾回收了?
问题:如何判断一个对象是否被垃圾回收了?
答案:
- 可以使用
PhantomReference
来判断对象是否被垃圾回收。当对象被垃圾回收时,PhantomReference
的get
方法会返回null
。 - 可以将
PhantomReference
添加到ReferenceQueue
中,当对象被垃圾回收时,ReferenceQueue
会收到通知。
7. 引用传递是按值传递还是按引用传递?
问题:Java中的引用传递是按值传递还是按引用传递?
答案:
- 按值传递:Java中的参数传递是按值传递的。对于基本类型,传递的是值的副本;对于引用类型,传递的是引用的副本。
- 按引用传递的副本:传递的是对象引用的副本,而不是对象本身。因此,可以通过引用修改对象的状态,但不能改变引用本身。
8. 如何避免内存泄漏?
问题:如何避免内存泄漏?
答案:
- 及时释放引用:不再使用的对象要及时释放引用,避免长时间持有无用对象的引用。
- 使用弱引用:在缓存和监听器等场景中,使用弱引用来避免内存泄漏。
- 静态变量谨慎使用:静态变量的生命周期与类相同,容易导致内存泄漏。
- 关闭资源:及时关闭文件句柄、数据库连接等资源,避免资源泄漏。
9. 什么是引用计数法?Java的垃圾回收器是否使用引用计数法?
问题:什么是引用计数法?Java的垃圾回收器是否使用引用计数法?
答案:
- 引用计数法:每个对象都有一个引用计数器,每当有一个地方引用它时,计数器加1;当引用失效时,计数器减1。当计数器为0时,对象可以被回收。
- Java的垃圾回收器:Java的垃圾回收器不使用引用计数法,而是使用可达性分析算法(Reachability Analysis)。通过从根节点(如栈帧中的局部变量表、方法区中的类静态属性)出发,遍历所有可达对象,未被遍历到的对象被视为垃圾,可以被回收。
10. 什么是可达性分析算法?
问题:什么是可达性分析算法?
答案:
- 可达性分析算法:从一系列称为"GC Roots"的对象开始,向下搜索,走过的路径称为引用链。当一个对象到GC Roots没有任何引用链相连时,证明此对象是不可达的,可以被垃圾回收。
- GC Roots:包括栈帧中的局部变量表、方法区中的类静态属性、本地方法栈中的JNI引用等。
11. 什么是弱引用表?它在垃圾回收中的作用是什么?
问题:什么是弱引用表?它在垃圾回收中的作用是什么?
答案:
- 弱引用表:垃圾回收器在进行垃圾回收时,会维护一个弱引用表,记录所有弱引用的对象。
- 作用:在垃圾回收过程中,垃圾回收器会检查弱引用表中的对象,如果这些对象没有其他强引用,就会被回收。弱引用表主要用于实现内存敏感的缓存和资源管理。
12. 如何使用 WeakHashMap
?
问题 :如何使用 WeakHashMap
?
答案:
-
WeakHashMap
:是一个基于弱引用的哈希表,键是弱引用,值可以是任意引用类型。 -
使用场景:适用于实现内存敏感的缓存,当键对象被垃圾回收时,对应的条目也会被移除。
-
示例代码 :
javaimport java.util.WeakHashMap; public class WeakHashMapExample { public static void main(String[] args) { WeakHashMap<String, String> map = new WeakHashMap<>(); String key = new String("key"); map.put(key, "value"); System.out.println(map.get(key)); // 输出 "value" key = null; System.gc(); // 请求垃圾回收 // 垃圾回收后,键对象被回收,对应的条目也被移除 System.out.println(map.get("key")); // 输出 null } }
13. 什么是引用队列?如何使用?
问题:什么是引用队列?如何使用?
答案:
-
引用队列 :
ReferenceQueue
是一个队列,用于接收被垃圾回收器回收的引用对象。 -
使用场景 :通常与
PhantomReference
一起使用,用于在对象被垃圾回收时收到通知。 -
示例代码 :
javaimport 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(); // 请求垃圾回收 // 检查引用队列 PhantomReference<?> ref = (PhantomReference<?>) queue.poll(); if (ref != null) { System.out.println("对象已被垃圾回收"); } } }
14. 什么是引用逃逸?如何避免?
问题:什么是引用逃逸?如何避免?
答案:
- 引用逃逸:在对象构造过程中,对象的引用被外部访问,导致对象在未完全构造完成的情况下被使用。
- 避免方法 :
- 私有化构造函数:将构造函数设为私有,通过工厂方法创建对象。
- 避免在构造函数中传递引用:不要在构造函数中将对象的引用传递给外部方法。
- 使用
final
修饰符 :将对象的属性设为final
,确保对象的不可变性。
15. 什么是引用透明性?Java中的引用是否透明?
问题:什么是引用透明性?Java中的引用是否透明?
答案:
- 引用透明性:在一个表达式中,如果可以用一个值替换另一个值而不改变程序的行为,那么这个表达式就是引用透明的。
- Java中的引用 :Java中的引用不是完全透明的,因为引用的赋值和传递可能会改变对象的状态。但是,对于不可变对象(如
String
),引用是透明的。