JPanel с анонимным EventListener - почему 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 и используйте это для доступа к методам, которые мне нужны для изменения параметров контроллера.

Чтобы сыграть в адвоката дьявола, если я пойду с оригинальной идеей и дам карте ссылку на свой контроллер, то теперь у меня есть своего рода круговая ссылка (карта знает о контроллере, а контроллер знает о карте). Это плохая идея?

2 ответа

Решение

Абстрактный родитель, JMapController, содержит ссылку на JMapViewer прошел там мимо DefaultMapController конструктор:

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

Приложение: The map ссылка, удерживаемая контроллером, используется (выборочно) для добавления до трех ссылок контроллера на карту EventListenerList обсуждается здесь. Любой из них исключает GC. По крайней мере одно полезное преимущество дизайна заключается в том, что бетон JMapController нужно только реализовать доступные интерфейсы.

Как предлагается в этом наброске MVC, было бы необычно давать представлению ссылку на контроллер. Напротив, нет ничего плохого в том, чтобы позволить контроллеру зарегистрироваться в качестве слушателя представления, как предлагается здесь.

Обратите внимание, что только без аргументов JMapViewer конструктор устанавливает DefaultMapController, Вы можете использовать альтернативный конструктор, как отмечено в комментариях в строке 57-59 в редакции 29113 Demo.java, Полный пример рассматривается здесь.

1) Все, что вы знаете, это то, что, если и когда виртуальная машина сочтет это целесообразным, она будет собирать некоторые или все мертвые объекты. GC не обязан ничего делать.

2) Лучше всего обратиться к хранителю библиотеки. В любом случае, как правило, я бы не стал ничего менять, если нет веской причины, например, если это заметно улучшает читабельность и скорее сосредоточится на реальных проблемах.

3) Не уверен, что это так, но когда вы сериализуете JComponent, вы также сериализуете все его поля. И вы не хотите сериализовать много неиспользованных вещей.

Другие вопросы по тегам