2012-03-19 1 views
6

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

перед:

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?

+0

не уверен, что я следую за вами, вы можете опубликовать метод подписи вверх и ваше «исправление» – Woot4Moo

+0

это может помочь вам http://stackoverflow.com/questions/3921616/java-leaking-this-in-constructor – Chikei

+0

[Java - утечка это в конструкторе] (http://stackoverflow.com/q/3921616/1048330) – tenorsax

ответ

0

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

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

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

0

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

+1

Плохое программирование, даже если в однопоточной среде. –

2

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

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

+1

Для автономных слушателей может оказаться полезным доступ к [* package-private *] (http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html). – trashgod

+1

Анонимные внутренние классы не решают проблему утечки 'this', хотя, если их экземпляры создаются в конструкторе. Это только затрудняет задачу, поскольку теперь «это» течет неявно. –

Смежные вопросы