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

标签 java swing garbage-collection event-listener jmapviewer

我一直在细读JMapViewer的开源代码.如果其他人想查看它,请检查 SVN .

简而言之,主类是JMapViewer,它是一个JPanel的扩展。还有另一个非常重要的类 DefaultMapController,它充当主类的 MouseListener

我注意到的第一件奇怪的事情是查看器没有对 Controller 的引用。 JMapViewer 构造函数实例化了 DefaultMapController 的匿名实例,如下所示:

public JMapViewer() {
    // other stuff
    new DefaultMapController(this);
}

在我看来,这似乎是一个糟糕的设计选择,因为 Controller 有大量的方法(选项、切换等 - 示例如下所示),现在根本无法访问,那么它们有什么用呢?

public void setMovementMouseButton(int movementMouseButton) {
    // changes which mouse button is used to move the map
}

Controller 确实有对查看器的引用,如上面第一个片段所示,这就是它能够行使控制权的方式。

不过,后来我想到了更奇怪的事情!如果监听器的这个匿名实例没有引用,为什么允许它生存呢? GC 不应该迅速销毁它吗?或者 GC 是否足够聪明,知道引用 Activity JComponent 的监听器类也必须保持 Activity 状态才能正常工作,即使它出于某种奇怪的原因没有名称也是如此?

那么,两个真正的问题:

  • 为什么 GC 不销毁对象?
  • 这确实是一个糟糕的设计选择,还是我不知道有什么方法可以从实例化查看器的类访问 Controller ?

我想为这个开源库做贡献,我的第一个改变想法是改变 JMapViewer 类,让它有一个字段引用它的 Controller ,并改变构造函数来分配当前这个新领域的匿名 Controller 。但是,我想确保我没有无知地遗漏一些东西。我在整个代码库中搜索了文本 DefaultMapController,它只出现在它自己的类定义中,以及 JMapViewer 构造函数中的匿名实例中。


编辑:

看来确实有一种方法可以访问匿名监听器,方法是使用 java.awt.Component 方法 getMouseListeners()。所以从技术上讲,在我的应用程序中,我可以在这个集合中搜索 DefaultMapController 的实例,并使用它来访问我需要用来更改 Controller 选项的方法。

尽管唱反调,如果我坚持最初的想法并为 map 提供其 Controller 的引用,那么现在我有一种循环引用( map 知道 Controller , Controller 知道 map )。这是个坏主意吗?

最佳答案

抽象父类 JMapController 持有对 JMapViewer 的引用,由 DefaultMapController 构造函数传递给那里:

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

附录: Controller 持有的map 引用用于(有选择地)将最多三个 Controller 引用添加到 map 的EventListenerList。 , 讨论 here .其中任何一个都会阻止 GC。至少一个有益的设计好处是具体的 JMapController 只需要实现可用的接口(interface)。

如本 MVC outline 中所建议, 给 View 一个 Controller 的引用是不寻常的。相比之下,让 Controller 注册为 View 的监听器并没有错,正如建议的那样here .

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

关于java - 带有匿名 EventListener 的 JPanel - 为什么 GC 不破坏监听器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14016262/

相关文章:

java - 为什么我得到 "no main class found"?

java - 如何设置 Swing 计时器在启动时执行

java - JTable 渲染器中的按钮文本不可见。为什么?

java - 如何使 Swing JTextArea 响应 KeyEvents?

java - 我的对象会被垃圾收集吗?

java - GC 花费了大量时间

python - PyO3 中对象向量的垃圾收集

Java 向 PHP 服务器发送 POST 数据被 accessRules 方法阻止

java - BasicPopupMenuUI 错误

java - spring boot中创建KafkaTemplate的正确方法