当前位置: 首页 > Linux

Java中的四种引用介绍

时间:2023-04-06 07:12:23 Linux

语录:我们知道Java和C相比,没有让人头疼的C++中的指针,但是有类似于指针的引用对象(Reference),也就是我们常说的引用,例如Objectobj=newObject();这个obj是一个引用,它指向的是真实对象Object的地址,但是今天要说的是java中的四种引用。可能有人会疑惑,四个引用?是的,从JDK1.2开始,Java扩展了引用的概念。根据引用的强度,分为四种类型的引用:强引用、软引用、弱引用和虚引用。下面我们就来看看这四个参考文献的具体情况。1.强引用1.1简介:我们代码中使用频率最高的引用,对象类是:StrongReference。比如上面提到的Objectobj=newObject();我们很熟悉,作为最强引用,只要引用还存在,垃圾回收器就不会回收引用,即使发生OOM(内存溢出))。也就是说,只要这种引用引用的对象仍然是指向的对象,垃圾回收器就不会管它,所以称为强引用。但是,如果Objectobj=newObject();对象=空;obj被赋值为null,引用就会被破坏,垃圾回收器会在合适的时候回收引用的内存。另一种情况是obj是一个成员变量。方法执行完后,obj会随着栈帧一起被回收,obj的引用也会一起被回收。强引用的使用就不介绍了,地球人都知道。2.软引用2.1简介:软引用用于描述一些有用但不需要的对象。对应的类是SoftReference,在系统内存不足时回收。如果内存足够,则不会回收。如果内存不足,可能会出现OOM,软引用的对象会被回收。像缓存这样的功能吗?是的,软引用可以用来存储缓存的数据,当内存充足时可以一直访问,当内存不足时,需要重新创建或访问原来的对象。2.2使用:其实无论是软引用,弱引用,还是幻引用,代码都是这样使用的,使用对应的Reference将对象放入构造函数中,然后使用placereference。get()调用特定对象。对象obj=newObject();SoftReferencesoftReference=newSoftReference<>(obj);softReference.get();同时,可以使用ReferenceQueue将引用与引用队列相关联:Objectobj=newObject();ReferenceQueuerefQueue=newReferenceQueue<>();SoftReferencesoftReference=newSoftReference<>(obj,refQueue);所谓关联,就是当引用被回收时,会被加入到ReferenceQueue中,使用ReferenceQueue.poll()方法可以返回当前可用的引用,并从队列中移除。简单的说,就是将引用关联到引用队列(引用的构造函数传入队列),然后引用被回收时会加入到队列中,然后使用poll()返回引用即可)方法。3.Weakreference3.1介绍:Phantomreference比上面两个reference还要差。只要垃圾回收器扫描到它,弱引用关联的对象就会被回收。与弱引用相关联的对象的生命周期实际上是从对象创建到下一次垃圾回收。对应的类是WeakReference。3.2使用:publicstaticvoidmain(String[]args)throwsInterruptedException{Objectobj=newObject();ReferenceQueuerefQueue=newReferenceQueue<>();WeakReferenceweakRef=newWeakReference<>(obj,refQueue);System.out.println("引用:"+weakRef.get());System.out.println("队列中的事物:"+refQueue.poll());//清除强引用,触发GCobj=null;系统.gc();线程.睡眠(200);System.out.println("引用:"+weakRef.get());System.out.println("引用入队了吗?"+weakRef.isEnqueued());System.out.println("队列中的事物:"+refQueue.poll());/***输出结果*reference:java.lang.Object@7bb11784*队列中的东西:null*reference:null*reference入队了吗?true*Thingsinthequeue:java.lang.ref.WeakReference@33a10788*/}可以看到当强引用被清除,手动触发GC时,弱引用被回收加入到队列中。3.3扩展:WeakHashMap与hashMap非常相似,不同的是当WeakHashMap的key(弱引用)指向的对象被回收时,weakhashMap中的对象也随之消失。它不会像HashMap一样一直持有对象,导致无法回收。就不细说了,有兴趣的可以了解一下WeakHashMap。4.幻引用4.1简介:幻引用是最弱的一种引用,它不会影响对象的生命周期,与被回收的对象无关。它所引用的对象可以随时被回收,没有办法根据虚引用来获取对象的实例。它只会在它指向的对象被回收时得到通知。对应的类是PhantomReference。4.2用途:有人会问,既然对对象回收没有影响,那它有什么用呢(其实很少有用)。网上查了资料说可以用来监控对象回收,记录日志。简单的说,当对象被回收时,虚引用相关的队列就知道实例对象被回收了。这个时候我们可以记录下来,知道这个对象是什么时候被回收的。从而起到监控的作用。publicstaticvoidmain(String[]args)throwsException{Objectabc=newObject();ReferenceQueuerefQueue=newReferenceQueue();PhantomReferenceabcRef=newPhantomReference(abc,refQueue);System.out.println("队列中有什么:"+refQueue.poll());abc=空;系统.gc();线程.睡眠(1000);System.out.println("引用队列是否已经存在?"+abcRef.isEnqueued());System.out.println("队列内容:"+refQueue.poll());/***输出:*Queuestuff:null*对enqueue的引用了吗?true*队列中的项:java.lang.ref.PhantomReference@7bb11784*/}如果队列中有引用,可以添加日志记录。5.总结:将人比作垃圾收集者,将引用比作食物,我们总结一下以下四种引用:强引用是毒药,即使你很饿也不会吃;软参考是零食,不是饿了饿了不吃,饿了不选吃,零食可以填饱肚子;弱引用就是吃饭,到了吃饭时间(垃圾回收),就可以吃菜了;phantomreferences是剩饭剩菜,当你吃完(回收对象)时,只要有剩饭剩菜,别人就会知道你吃过了。5.1表对比:引用回收时序使用场景strong不会被回收正常代码使用软内存不够用,可以被GC用作缓存weakGC可以在GC发生时用作缓存(WeakHashMap)虚拟监听对象随时回收、记录日志参考资料:1.https://blog.csdn.net/l540675...2.https://www.iteye.com/topic/5...3.https://www.geeksforgeeks。org...4.https://blog.csdn.net/aitangy...