java有四种引用类型
强引用、软引用、弱引用、虚引用,接下来分别讲一下他们的概念和我遇到过的实际应用类型。
强引用就是我们平时使用的引用类型,只要指向对象的变量继续存在,变量指向的对象就不会被回收。
StringBuffer buffer = new StringBuffer();
弱引用,只要没有任何其他强引用引用到这个弱引用指向的对象,这个弱引用指向的对象就可能会被回收,当你想引用一个对象,但是这个对象有自己的生命周期,你不想介入这个对象的生命周期,这时候你就是用弱引用。
例如下图,该weakReference指向的对象随时可能被回收
WeakReference<User>weakReference=new WeakReference<User>(new User());
接下来说一说我在实际项目中对弱引用的应用。
在我开发的一个游戏框架中有各种各样的单例管理器对象,例如游戏对象管理器,所有游戏对象一旦创建会被自动加入该管理器,方便对游戏对象的整体管理,包括实际各种缓存策略,对象池之类的。
现在假设我们需要在地图加载完成后创建一个怪物,那么此时就有两个地方引用到该对象(一般情况下要多得多,这里做简化),分别是创建该对象的代码处。以及自动加入的对象管理器处。
此时如果怪物死亡后,单纯的在代码块中设置怪物为null并不能使gc回收怪物对象,因为游戏对象管理器还一直引用着怪物。
但是作为一个框架,我们不希望开发者需要调用例如 manager.remove(object)这样的代码来将怪物对象从对象管理器中移除,这个时候弱引用就派上了用场。
我们可以在所有单例管理器需要引用到怪物对象的地方,都用弱引用来引用,这样就可以将框架代码和用户代码完全分离,开发者只需要将一个对象设置为null,就可以让gc回收他,而不用调用框架代码,一个一个的从单例管理器中去除这个对象。
(当然还有另外一种方法,就是用一个内置在对象中的方法来完成这些remove操作。例如object.destroy(),每次移除对象之前调用destroy方法,而不是设置为null,然后在destroy中从管理器中将自身移除,两种方法都各有好处,这里不细说了)
软引用
软引用的移除逻辑和弱引用相同,唯一的区别是软引用在内存充足时并不会回收对象,只有内存不足时才会回收只有软引用指向的对象。
软引用比较适用于构建图片缓存之类的东西,我之前的项目中就使用软引用来实现一个图片缓存,当加载图片时首先查询图像缓存,如果有的话直接返回缓存,没有的话先加载到缓存中,再返回。
当然这样带来的一个问题就是图像缓存会越来越大,虽然也可以自己实现回收算法, 但是使用软引用在内存不足的时候自动回收引用更加简单。
虚引用
虚引用主要用来观测对象什么时候被回收,
(这个实际我在项目中没怎么用过)。