将监听器保留为弱引用的优缺点是什么?
显然最大的“优点”是:
将监听器作为弱引用添加,意味着监听器不需要费心“移除”自己。
对于那些担心监听器是对象唯一引用的人,为什么不能有两种方法:addListener()和addWeakRefListener()?
那些不关心移除的人可以使用后者。
将监听器保留为弱引用的优缺点是什么?
显然最大的“优点”是:
将监听器作为弱引用添加,意味着监听器不需要费心“移除”自己。
对于那些担心监听器是对象唯一引用的人,为什么不能有两种方法:addListener()和addWeakRefListener()?
那些不关心移除的人可以使用后者。
addWeakListener(listener)
这样利用weakrefs命名方法可能是一个好习惯,因为这个类的用户会知道内部发生了什么,以避免错过通知。 - vir us这不是一个完整的答案,但你提到的优点也可能是其主要缺点。如果弱化实现操作监听器,请考虑会发生什么:
button.addActionListener(new ActionListener() {
// blah
});
那个动作监听器随时都可能被垃圾回收!这并不罕见,只有事件与其相关联的匿名类才是对它的唯一引用。
我看到过大量的代码没有正确注销监听器。这意味着它们仍然被不必要地调用以执行不必要的任务。
如果只有一个类依赖于监听器,那么清理就很容易,但是当25个类都依赖于它时会发生什么?正确注销它们变得更加棘手。事实上,您的代码可能从引用一个监听器对象开始,最终在未来版本中引用了同一个监听器的25个对象。
不使用 WeakReference
相当于冒着消耗不必要的内存和 CPU 的风险。在复杂的代码中,它更加复杂、棘手并且需要更多的工作来处理硬引用。
WeakReferences
充满优点,因为它们会自动清理。唯一的缺点是,在代码的其他地方必须记得保留一个硬引用。通常,这将在依赖此监听器的对象中进行。
我讨厌创建监听器的匿名类实例的代码(正如 Kirk Woll 所提到的),因为一旦注册,你就无法注销这些监听器了。你没有对它们的引用。我认为这是糟糕的编程。
当你不再需要监听器时,你也可以将对监听器的引用置为 null
。这样你就不必再担心它了。
在我看来,在大多数情况下这是一个好主意。释放监听器的代码与注册它的代码位于同一位置。
实际上,我看到很多软件会永久保留监听器。通常程序员甚至不知道他们应该注销它们。
通常可以返回一个包含对监听器引用的自定义对象,以便可以控制注销的时间。例如:
listeners.on("change", new Runnable() {
public void run() {
System.out.println("hello!");
}
}).keepFor(someInstance).keepFor(otherInstance);
on()
之后但在keepFor()
之前发生垃圾回收怎么办?假设keepFor()
调用了weakReference.get()
,此时可能已经返回null
了? - glebm