前言
本篇文章会简单介绍一下,什么是java中的引用,并介绍java中四种引用类型,强引用,软引用,弱引用,虚引用。
一、java中引用
Java不像C语言那样有着明确的指针的概念,因此很多程序员对引用和对象有些分不清。
作为一个Java程序猿,下面的程序我们肯定很熟悉。
Object obj = new Object();
这段代码中在new Object()的时候在堆中创建了一个Object类型的对象,并且把这个对象的相关信息给了obj引用。两者的关系好比是气球(不可以直接触碰的气球)和绳子,对象就是这个气球,我们没办法直接操作,引用好比气球绳,我们可以通过这根绳子从而操作与绳子连接的气球。
对象也是如此,我们没办法直接去修改堆内存中的对象,我们可以通过引用找到堆内存进而进行修改
。
有时候在工作中,有人直接说上述例子中的obj就是对象,其实这种说法不太严谨,obj只是这个对象的引用而已,不过真有人这么说也不用太较真,知道什么意思即可。
二、引用类型
1.强引用
强引用是引用关系中最常见的一种,例如上边的例子就是一种强引用。垃圾回收器不会回收还存在强引用关系的对象。代码示例如下:
Object object = new Object();
System.out.println(object);//java.lang.Object@1b6d3586
System.gc();
System.out.println(object);//java.lang.Object@1b6d3586
//删除对象的话,只需讲引用置为null,之后垃圾回收器认为该对象是不可达对象就会自动回收
object = null;
System.out.println(object);
由于强引用关系在,对象不会回收,强引用也是造成Java内存泄露的主要原因之一。
2.软引用
软引用是SoftReference 类实现的。对于内存足够的时候,软引用连接的对象是不会被删除的,但是当内存不够的时候,软引用连接的对象就会被垃圾收集器回收。代码如下
//前提 设置-Xms10M -Xmx10M
SoftReference<byte[]> softReference = new SoftReference<>(new byte[1024 * 1024 * 4]);
System.out.println(softReference.get()); //[B@1b6d3586
System.gc();
System.out.println(softReference.get()); //[B@1b6d3586
byte[] bytes = new byte[1024 * 1024 * 4];
System.out.println(softReference.get()); //null
上述代码中我们先打印了下引用[B@1b6d3586,当我们手动进行了gc后,引用打印出来还是[B@1b6d3586。当我们在创建一个4M数据大小的数组后,我们打印出来就变成null。
(笔者使用的java8默认的垃圾回收器)我们设置堆内存10M,新生代内存大约3.3M,老年代大约6.6M。我们手动gc时内存充足,因此软引用的对象没有回收。当我们创建一个强引用bytes的数组对象时,内存分配不下,因此jvm进行了一次gc,认为内存不够,就把软引用的对象给回收了
3、弱引用
弱引用是WeakReference类实现的。是一种比软引用还弱的引用,当我们下一次gc的时候,对象内存就会被回收,不管内存够不够。代码示例如下
WeakReference<byte[]> weakReference = new WeakReference<>(new byte[1024 * 1024 * 1]);
System.out.println(weakReference .get()); //[B@1b6d3586
System.gc();
System.out.println(weakReference .get()); //null
我们的堆内存还有剩余,但是gc的时候还是把对象内存回收了。
4、虚引用
虚引用是PhantomReference类实现的。虚引用好比没有引用一样,在gc中会被回收,与弱引用不同的是,弱引用在被回收前可以拿到实例化的相关数据,而虚引用是无法通过引用找到实例的。因此又被成为幽灵引用。
总结
以上就是今天要讲的内容,本文简单介绍了什么是引用,以及java中存在的四种引用,强引用,软引用,弱引用,虚引用的相关知识。四种引用从强度的关系来看,强引用>软引用>弱引用>虚引用。