简介
java语言中由于不同的使用场景的不同需求,对着引用的等级有着不同的需求。本文主要介绍了包括强引用、软引用、弱引用和虚引用4种不同的引用类型。
1. 强引用
强引用的生成方式:
User a = new User();
1.1 强引用特点
一般来说我们直接new出来的对象就是强引用,对于垃圾回收器来说,只有强引用的对象在没有引用的时候才会被回收。
2. 软引用
软引用实际上在java的java.lang.ref包中被定义了,软引用的定义如下:
java.lang.ref.SoftReference
软引用对象的定义方法如下:
SoftReference<User> userSoftRef = new SoftReference<>(new User());
2.1 软引用特点
软引用的特点是他很软,软在哪里呢?
他的性格很软!!!
为什么这么说呢,当内存空间不足的时候,垃圾回收器会优先把软引用的对象回收掉!就是说,在内存不够的时候,软引用就是一个软柿子,被随意拿捏回收!
2.2 软引用应用场景
软引用很适合用在缓存场景,用软引用实现的缓存,可以在内存不足的时候自动释放,对软件的主功能影响小。可以维护系统的运行安全,防止内存溢出(OutOfMemory)
3 弱引用
弱引用也在java.lang.ref包里面被定义了
java.lang.ref.WeakReference
弱引用的使用方法:
WeakReference<User> userWeakReference = new WeakReference<>(new User());
3.1 弱引用的特点
弱引用实际上他的性格不软,垃圾回收器要回收他,他是轻易不干的,他的特点是很弱。为啥说他弱呢?因为他在引用计数为1的时候就无法阻止垃圾回收器去GC他,可以说虽然有保护自己的心,但是属于心有余而力不足。
3.2 弱引用的应用场景
在java的ThreadLocal中被用到,这个我专门写了一片文章来介绍:
https://blog.csdn.net/qq_40301372/article/details/131744554?spm=1001.2014.3001.5502
4. 虚引用
虚引用必须要和引用队列配合使用,以下是使用方法:
// 新建一个对象
User obj = new User();
// 存储被回收的对象
ReferenceQueue<User> QUEUE = new ReferenceQueue<>();
// phantomReference使用虚引用指向这个内存空间
PhantomReference<User> phantomReference = new PhantomReference<>(obj, QUEUE);
4.1 虚引用的特点
(1)虚引用无法get()得到引用的对象
// 获取不到,打印为null
System.out.println(phantomReference.get());
(2) 虚引用可以在被回收的时候收到通知,通过这种方式监控一些堆外引用
public static void main(String[] args) {
// 新建一个对象,开辟一个内存空间
User obj = new User();
// 存储被回收的对象的虚引用对象
ReferenceQueue<User> QUEUE = new ReferenceQueue<>();
// phantomReference使用虚引用指向这个内存空间
PhantomReference<User> phantomReference = new PhantomReference<>(obj, QUEUE);
// 释放这个内存空间,此时只剩phantomReference通过虚引用指向它
obj = null;
// 调用gc回收new User的内存空间
System.gc();
// 被清除的队列中取出被回收的对象
while (true) {
Reference<? extends User> poll = QUEUE.poll();
if (poll!=null) {
System.out.println("--obj is recovery--");
}
}
}
举个例子,会对应生成一个客户端和数据库服务的真实存在的网络连接,当查询完数据后,可以通过connection.close()方法关闭这个连接,但是。如果忘了写这句关闭的代码难道就永远保持连接吗?那必然是不行的,所以mysql驱动使用了虚引用,在Connection对象被垃圾回收时,自动执行关闭网络连接的方法。