我一直在阅读 JMapViewer的开源代码。如果其他人希望查看它,请检查SVN。
简而言之,主类是JMapViewer
,它是 a 的扩展JPanel
。还有另一个非常重要的类称为DefaultMapController
主MouseListener
类。
我注意到的第一件奇怪的事情是查看器没有对控制器的引用。构造JMapViewer
函数实例化 的匿名实例DefaultMapController
,如下所示:
public JMapViewer() {
// other stuff
new DefaultMapController(this);
}
在我看来,这似乎是一个糟糕的设计选择,因为控制器有大量的方法(选项、切换等 - 示例如下所示),现在根本无法访问,那么它们有什么好处呢?
public void setMovementMouseButton(int movementMouseButton) {
// changes which mouse button is used to move the map
}
如上面的第一个片段所示,控制器确实具有对查看器的引用,这就是它能够行使控制的方式。
然而,我想到了更奇怪的事情!如果侦听器的这个匿名实例没有引用,为什么还要允许它存活呢?GC不应该快速销毁它吗?或者 GC 是否足够聪明,可以知道引用 live 的侦听器类也JComponent
必须保持活跃才能正常工作,即使由于某种奇怪的原因它没有名称?
所以,两个真正的问题:
- 为什么 GC 不销毁对象?
- 这确实是一个糟糕的设计选择,还是有某种我不知道从实例化查看器的类访问控制器的方式?
我想为这个开源库做出贡献,我的第一个更改想法是更改JMapViewer
类以具有引用其控制器的字段,并更改构造函数以将当前匿名控制器分配给这个新字段。但是,我想确保我不会无知地遗漏一些东西。我已经在整个代码库中搜索了 text DefaultMapController
,它只出现在它自己的类定义中,以及JMapViewer
构造函数中的匿名实例中。
编辑:
确实似乎有一种方法可以通过使用java.awt.Component
method来访问匿名侦听器getMouseListeners()
。所以从技术上讲,在我的应用程序中,我可以在这个集合中搜索 的实例DefaultMapController
,并使用它来访问我需要用来更改控制器选项的方法。
不过,为了扮演魔鬼的拥护者,如果我按照最初的想法为地图提供其控制器的引用,现在我有一种循环引用(地图知道控制器,控制器知道地图)。这是一个坏主意吗?