编程语言
首页 > 编程语言> > java – 带有匿名EventListener的JPanel – 为什么GC不会破坏监听器?

java – 带有匿名EventListener的JPanel – 为什么GC不会破坏监听器?

作者:互联网

我一直在阅读JMapViewer的开源代码.如果有人想看一下,请查看SVN.

简而言之,主类是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的实例,并使用它来访问我需要用来更改控制器选项的方法.

但是,为了扮演魔鬼的拥护者,如果我按照原始想法并给地图作为其控制器的参考,现在我有一种循环参考(地图知道控制器和控制器知道地图).这是一个坏主意吗?

解决方法:

抽象父JMapController包含对DefaultMapController构造函数传递的JMapViewer的引用:

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

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

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

请注意,只有无参数的JMapViewer构造函数会安装DefaultMapController.您可以使用备用构造函数,如Demo.java版本29113中第57-59行的注释中所述.完整的例子在here进行了检查.

标签:event-listener,java,garbage-collection,swing,jmapviewer
来源: https://codeday.me/bug/20190929/1833057.html