Утечка this в конструкторе - где правильно добавить слушателей и другие методы, требующие «this» - PullRequest
7 голосов
/ 19 марта 2012

У меня есть класс, который расширяет JPanel. В своем конструкторе я передаю this другим методам, главным образом для добавления объекта jpanel в качестве слушателя к контейнерам / элементам управления внутри jpanel (но также и другим объектам). Поскольку Netbeans отображает предупреждение leaking this in constructor для этих вызовов, я поместил их в другой метод, который вызывается из конструктора.

перед:

class Foo ... {
    public Foo() {
      initComponents();
      tabX.addChangeListener(this); // <- netbeans complains here
    }

после

class Foo ... {
    public Foo() {
      initComponents();
      initListeners();
    }

    protected void initListeners() {
      tabX.addChangeListener(this);
    }

Это избавляет от симптома. Но я сомневаюсь, что это исправляет причину, по которой netbeans показывает предупреждение.
Где правильное место для инициализации такого рода в классе, производном от JPanel?

Ответы [ 3 ]

2 голосов
/ 19 марта 2012

Интересно, есть ли здесь более серьезная проблема - попросить вашего класса сделать слишком много? Класс должен иметь одну главную цель, и представление должно отвечать за представление, и все. Чтобы заставить его выполнять функции модели или управления, и вы потеряете сплоченность , вы можете увеличить сцепление и рискнуть создать божественные объекты, которые трудно, если не невозможно, отладить или расширить. Говоря прямо, классы GUI или представления должны , а не также быть классами слушателей. Другими словами, для класса GUI нет веской причины и много плохих причин для реализации интерфейса слушателя.

Лучшее решение: не используйте классы GUI для реализации слушателей. Вместо этого либо используйте анонимные внутренние классы, либо закрытые внутренние классы, либо, если они достаточно сложны, или вы ожидаете расширения и / или изменения своего кода в будущем, автономные классы слушателей.

0 голосов
/ 19 марта 2012

Причина этого предупреждения заключается в том, что вы передаете его, пока конструктор не завершен и, следовательно, объект не полностью инициализирован. Даже если вы используете его в конце вашего конструктора, есть вероятность, что ваш класс расширен и есть конструктор подкласса, который еще предстоит выполнить. В вашем случае (регистрация объекта в качестве слушателя) это безопасно, поскольку Swing является однопоточным, а события будут передаваться слушателям только после инициализации вашего объекта.

0 голосов
/ 19 марта 2012

Я предполагаю, что вы, вероятно, добавляете расширение JPanel к другому компоненту (например, JFrame, JApplet, другому JPanel и т. Д.).Вы упомянули, что у вас есть некоторая смесь между необходимостью добавления панели к подкомпонентам в этой панели и «другими объектами», которые панель должна слушать.Вероятно, было бы лучше добавить панель к этим «другим объектам» рядом с местом, где вы добавляете расширение JPanel к включающему его JFrame или другому родительскому компоненту, вне определения класса вашего расширения.

Тем не менее, для подкомпонентов вашей панели, которые должна прослушивать ваша панель, я думаю, что вы делаете хорошо, если эти подкомпоненты не видны объектам вне вашего определения класса расширения JPanel.Это предупреждение просто указывает на то, что то, что вы делаете, может быть небезопасным, но в конечном итоге, когда ваша панель будет собирать мусор, будут поступать все принадлежащие ей подкомпоненты, включая любые списки прослушивателей, на которые они ссылаются.ваше JPanel расширение.Из-за этого я считаю, что помещать вызов add*Listener(this) в закрытый метод с подходящим именем для вашего расширения JPanel и вызывать его из вашего конструктора вполне нормально.

Другой вариант - использовать Eclipse.так что вы больше не получаете эти предупреждения ... (шутка;).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...