2

我一直在阅读 JMapViewer的开源代码。如果其他人希望查看它,请检查SVN

简而言之,主类是JMapViewer,它是 a 的扩展JPanel。还有另一个非常重要的类称为DefaultMapControllerMouseListener类。

我注意到的第一件奇怪的事情是查看器没有对控制器的引用。构造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.Componentmethod来访问匿名侦听器getMouseListeners()。所以从技术上讲,在我的应用程序中,我可以在这个集合中搜索 的实例DefaultMapController,并使用它来访问我需要用来更改控制器选项的方法。

不过,为了扮演魔鬼的拥护者,如果我按照最初的想法为地图提供其控制器的引用,现在我有一种循环引用(地图知道控制器,控制器知道地图)。这是一个坏主意吗?

4

2 回答 2

6

抽象父级,JMapController持有JMapViewer对构造函数传递到那里的引用DefaultMapController

public DefaultMapController(JMapViewer map) {
    super(map);
}

附录:map控制器持有的引用用于(有选择地)将最多三个控制器引用添加到地图的EventListenerList,在此处讨论。其中任何一项都会排除 GC。至少一个有益的设计好处是具体JMapController需要只实现可用的接口。

正如这个MVC 大纲中所建议的,给视图提供对控制器的引用是不寻常的。相比之下,让控制器注册为视图的侦听器并没有错,正如这里所建议的那样。

请注意,只有无参数JMapViewer构造函数会安装DefaultMapController. 您可以使用备用构造函数,如Demo.java. 此处检查了一个完整的示例。

于 2012-12-24T02:29:27.263 回答
1

1)您所知道的一切是,如果VM认为合适,它将收集部分或全部死对象。GC 不需要做任何事情。

2)最好的办法是向图书馆的维护者询问。无论如何,作为一般规则,我不会费心去改变任何东西,除非有充分的理由,例如,如果它明智地提高了可读性,并且宁愿让自己专注于真正的问题。

3) 不确定是否是这种情况,但是,当您序列化 JComponent 时,您还序列化了它的所有字段。而且您不想序列化很多未使用的东西。

于 2012-12-24T02:08:07.263 回答