@mapperscan mapper还是无法引用_强、软、弱、虚,你是哪一种“引用”?

点击蓝字

4bc45e94-f236-eb11-8da9-e4434bdf6706.svg

关注我们

前言

每种编程语言都有自己操作内存中元素的方式,例如在 C 和 C++ 里是通过指针,对于指针的使用,大家肯定记得刚学习时候的痛苦。

作为 OOP 面向对象编程的翘楚,在 Java 中一切都被视为了对象。但其实操作时候的标识符并不是真正的对象,而是对象的一个引用(reference)。

通过将这个叫“引用”的标识符指向某个对象,之后便可以使用这个引用来实现操作对象了。

在 JDK1.2 之前,Java中的定义很传统:如果 reference 类型的数据中存储的数值代表的是另外一块内存的起始地址,就称为这块内存代表着一个引用。

Java 中的垃圾回收机制在判断是否回收某个对象的时候,都需要依据“引用”这个概念。不同垃圾回收算法中,对引用的判断方式有所不同,典型的有引用计数法和可达性分析法。

大家可以看我之前写过的文章:

《面了BAT,我总结了他们会问的JVM基础知识》

《肝完这篇垃圾回收,和面试官扯皮不怕了》

JDK1.2 之前,一个对象只有“已被引用”和"未被引用"两种状态,这将无法描述某些特殊情况下的对象,比如,当内存充足时需要保留,而内存紧张时才需要被抛弃的一类对象。

所以在 JDK.1.2 之后,Java 对引用的概念进行了扩充,将引用分为了:强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Weak Reference)、虚引用(Phantom Reference)4 种,这 4 种引用的强度依次减弱。

本篇文章将对这四种引用类型进行详细介绍,码字不易,别忘了「在看」,「转发」哦。

正文

强引用

在 Java 中,我们默认声明的时候,使用的是强引用,比如:

A a = new A();

只要使用了强引用,垃圾回收器将永远不会回收被引用的对象。由于内存大小是一定的,当内存不足时,JVM 会直接抛出 OutOfMemoryError,因为没办法回收去释放空间。

如果想中断强引用与对象之间的关系,可以显示将其赋值为 null,这样一来JVM 就可以在适当的时候进行垃圾回收了。

A a = null;

软引用

软引用比强引用的程度减弱一些,表示是一些非必需但仍有用的对象。它的表现形式如下:

(1)内存足够的时候,软引用对象不会被回收。

(2)内存不足时,系统则会回收软引用对象。

如果软引用对象被回收之后,仍然没有足够的内存空间,然后会抛出内存溢出异常。

由于软引用的这种特性,非常适合实现缓存技术,比如网页缓存,图片缓存等等。

在 JDK1.2 之后,用java.lang.ref.SoftReference类来表示软引用。

弱引用

弱引用的强度还要更弱一些,它最主要的特点是:无论内存是否足够,只要 JVM 开始进行垃圾回收,那些被弱引用关联的对象都会被回收

在 JDK1.2 之后,用 java.lang.ref.WeakReference 来表示弱引用。

我们可以用下面的小demo来测试一下:

private static void testWeakReference() {        for (int i = 0; i 10; i++) {            byte[] buff = new byte[1024 * 1024];            WeakReference<byte[]> sr = new WeakReference<>(buff);            list.add(sr);        }        System.gc(); //主动通知垃圾回收        for(int i=0; i             Object obj = ((WeakReference) list.get(i)).get();            System.out.println(obj);        }    }

运行后会发现所有被弱引用关联的对象都被垃圾回收了。

在学习弱引用的时候,一个经典的例子就是 ThreadLocal,通过源代码我们发现它的内部数据结构就是由弱引用来实现的。

 static class ThreadLocalMap {        /**         * The entries in this hash map extend WeakReference, using         * its main ref field as the key (which is always a         * ThreadLocal object).  Note that null keys (i.e. entry.get()         * == null) mean that the key is no longer referenced, so the         * entry can be expunged from table.  Such entries are referred to         * as "stale entries" in the code that follows.         */        static class Entry extends WeakReference<ThreadLocal>> {            /** The value associated with this ThreadLocal. */            Object value;            Entry(ThreadLocal> k, Object v) {                super(k);                value = v;            }        }}

在使用 ThreadLocal 时如果忘记了remove操作,很容易出现内存泄露的问题,后续有时间我会专门写一篇文章再讲讲这个。

虚引用

虚引用是最弱的一种引用关系,如果一个对象仅持有虚引用,那么它就和没有任何引用一样,它随时可能会被回收。

在 JDK1.2 之后,用 PhantomReference 类来表示,通过查看这个类的源码,发现它只有一个构造函数和一个 get() 方法,而且它的 get() 方法仅仅是返回一个 null,也就是说将永远无法通过虚引用来获取对象,虚引用必须要和 ReferenceQueue 引用队列一起使用。

public class PhantomReference<T> extends Reference<T> {    /**     * Returns this reference object's referent.  Because the referent of a     * phantom reference is always inaccessible, this method always returns     * null.     *     * @return  null     */    public T get() {        return null;    }    public PhantomReference(T referent, ReferenceQueue super T> q) {        super(referent, q);    }}

总结

通过这篇文章介绍了 Java 语言中的四种引用类型,看完后我们发现这主要与Java 的垃圾回收机制和内存管理息息相关。JVM 作为基础,还是希望大家能够扎实的掌握。

7aad5ef803c1bed06cf8035bcb8d00e6.gif

往期推荐

01

●优秀程序员应该具备的几个特质,你有吗?

► 点击阅读

02

●35岁是程序员工作的终点?非标准答案在这里

► 点击阅读

03

●搜狗改姓“马”,腾讯要将搜狗召进宫

► 点击阅读

04

● 《抱歉,这就是生活》——但是,请不要灰心

► 点击阅读

好文!记得点击 “在看”
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值