2012-12-24 117 views
2

我一直在仔细阅读JMapViewer的开源代码。如果有其他人希望查看它,请检查SVN与匿名EventListener的JPanel - 为什么不GC摧毁监听器?

简而言之,主类是JMapViewer,它是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足够聪明地知道引用活动JComponent的监听器类也必须保持活动才能正常工作,即使它因某种奇怪的原因而没有名称?

所以,两个真正的问题:

  • 为什么GC不破坏对象?
  • 这是一个糟糕的设计选择,还是有一些我不知道从实例化查看器的类访问控制器?

我想参与这个开放源码库,和我换一换的第一个想法是改变JMapViewer类有一个字段引用它的控制器,并且改变构造函数,当前匿名控制器分配给此新领域。但是,我想确保我不会无知地错过什么。我已经搜索了整个代码库文本DefaultMapController,并且它只出现在它自己的类定义中,以及JMapViewer构造函数中的匿名实例化中。


编辑:

它似乎的确有访问匿名听众,通过使用java.awt.Component方法getMouseListeners()的方式。因此,在技术上,我可以在我的应用程序中搜索此集合中的DefaultMapController实例,并使用它来访问我需要用来更改控制器选项的方法。如果我按照原来的想法去给它的控制器一个引用,现在我有一种循环引用(地图知道控制器和控制器知道地图)。这是一个坏主意吗?

+0

为了方便起见,我添加了一个[tag:jmapviewer]标签,但我依照您的意见使用它。引用来源为+1。 – trashgod

+1

@trashgod谢谢。我用'JMapViewer'替换了'JPanel'标签。 – The111

回答

6

的抽象父,JMapController,保持对所述JMapViewerDefaultMapController构造通过那里的引用:

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

附录:由控制器保持的map引用用于(选择性地)添加三个控制器参考地图的EventListenerList,讨论了here。其中任何一个都会阻止GC。至少有一个有益的设计好处是具体的JMapController只需要实现可用的接口。

正如在MVC outline中所建议的那样,为视图提供对控制器的引用是不正常的。相反,让控制器注册为视图的监听器没有任何问题,如建议here

请注意,只有无参数JMapViewer构造函数安装DefaultMapController。您可以使用替代构造函数,如Demo.java修订版29113中第57-59行的注释中所述。一个完整的例子被检查here

+1

让它变成垃圾,让垃圾箱潜入一小撮代码中。做得好,1+。 –

+0

对,我在帖子中说过。它是'DefaultMapController',它没有对它的引用。非常感谢您深入研究代码,并不期望任何人这样做。 :-) – The111

+0

我编辑了问题的标题,以防它不清楚。 – The111

1

1)你所知道的一切是,如果当VM认为它是合适的,它会收集一些或所有的死对象。 GC不需要做任何事情。

2)最好的办法是问问图书馆的维护人员。无论如何,作为一般规则,除非有充分的理由,例如,我不打算改变任何东西。如果明智地提高了可读性,并且宁愿专注于真正的问题。 3)不确定是否是这种情况,但是当你序列化一个JComponent时,你也要序列化它的所有字段。而且你不想序列化很多未使用的东西。

+0

有一个很好的理由去改变它。我在我的应用程序中调用了'JMapViewer'类,并希望控制器的行为稍有不同。已经有控制器方法来创建我想要的行为。但是,由于控制者是匿名的,他们无法访问。图书馆没有得到非常积极的维护,但我确实试图从他们那里找出这个设计的原因。 – The111