前言
在上一篇文章的示例中还应该注意到,
Frog对象拥有其自己的成员对象。
Frog对象创建了它自己的成员对象,并且知道它们存活多久(只要
Frog存活着),因此
Frog对象知道何时调用
dispose()去释放其成员对象。然而,如果这些成员对象中存在于其他一个或者多个对象共享的情况,问题就变得更加复杂了,你就不能简单地假设你可以调用
dispose()了。在这种情况下,也就必需使用引用计数来跟踪仍旧访问着共享对象的对象数量了。下面是相关的代码:
示例源码
package com.mufeng.theeighthchapter;
class Shared {
private int refcount = 0;
private static long counter = 0;
private final long id = counter++;
public Shared() {
// TODO Auto-generated constructor stub
System.out.println("Creating " + this);
}
public void addRef() {
refcount++;
}
protected void dispose() {
if (--refcount == 0) {
System.out.println("Disposing " + this);
}
}
@Override
public String toString() {
// TODO Auto-generated method stub
return "Shared " + id;
}
}
class Composing {
private Shared shared;
private static long counter = 0;
private final long id = counter++;
public Composing(Shared shared) {
// TODO Auto-generated constructor stub
System.out.println("creating " + this);
this.shared = shared;
this.shared.addRef();
}
protected void dispose() {
System.out.println("disposing " + this);
shared.dispose();
}
@Override
public String toString() {
// TODO Auto-generated method stub
return "Composing " + id;
}
}
public class ReferenceCount {
public static void main(String[] args) {
Shared shared = new Shared();
Composing[] composing = { new Composing(shared), new Composing(shared),
new Composing(shared), new Composing(shared),
new Composing(shared) };
for (Composing c : composing) {
c.dispose();
}
}
}
输出结果
Creating Shared 0
creating Composing 0
creating Composing 1
creating Composing 2
creating Composing 3
creating Composing 4
disposing Composing 0
disposing Composing 1
disposing Composing 2
disposing Composing 3
disposing Composing 4
Disposing Shared 0
源码解析
static long counter跟踪所创建的
Shared的示例的数量,还可以为
id提供数值。
counter的类型是
long而不是
int,这样可以防止溢出。
id是
final的,因为我们不希望它的值在对象生命周期中被改变。
在将一个共享对象附着到类上时,必须记住调用
addRef(),但是
dispose()方法将跟踪引用数,并决定何时执行清理。使用这种技巧需要加倍地细心,但是如果你正在共享需要清理的对象,那么你就没有太多的选择余地了。