在项目中,我们可以通过合理地使用不同类型的引用来优化内存使用性能.
1.强引用 : String str = new String("123"); str 称为强引用。一个对象如果一直存在强引用,则不会被垃圾回收。
2.弱引用:
String str = new String("123");
SoftReference<String> sft = new SoftReference<String>(str);
str = null;
如果一个对象只存在弱引用关系,当虚拟机内存空间不足时,会回收对象. 否则不会回收对象
3.软引用: 如下
String str = new String("123");
Map weakMap = new WeakHashMap<>();
weakMap.put(str);
str = null;
如果一个对象只存在弱引用,当虚拟机垃圾回收时,一定会回收该对象.
4.虚引用 PhantomRefernce
虚引用必须和引用队列(ReferencQueue)一起使用.啥意思? 就是说 一个对象要建立虚引用关系,必须通过引用队列, 我们在获取它的值时 也要通过引用队列获取.
String str = new String("123");
ReferenceQueue<String> refQueue = new Reference<String>(); // 引用队列
PhantomReference<String> phantom = new PhantomReference<String>(str,refQueue); //通过引用队列建立虚引用关系.
str = null; // 释放强引用对象
// 从引用队列获取待回收的对象
Object obj = referenceQueue.poll();
if(obj !=null ){
Field rereferentVal = null;
try{
// 通过反射 ,得到待回收的对象的值
rereferentVal = Refrence.class.getDeclaredField("referent");
rereferentVal.setAccessible(true);
System.out.println("Before GC Clear: "+ rereferentVal.get(obj).toString());
}catch(Execption e){
e.printStackTrace();
}
}
通过虚引用,我们可以在对象被回收后从引用队列中得到它的引用,并能在合适的代码位置通过这个引用执行对该对象的析构操作.
关于虚引用的几条:
(1) 我们始终无法通过虚引用得到它所指向的值,因为通过虚引用,一般只能拿到null值.
(2) 通过虚引用,我们可以在对象被回收后,通过引用队列调用该对象的析构方法.
(3) 如果不做任何操作,在引用队列referenceQueue 中存放的对象的内存是无法被回收的,所以在放入后,一定要通过poll方法吧虚引用从队列中取出.