2012-03-19 28 views
6

我有一個擴展了JPanel的類。在其構造函數中,我將this傳遞給其他方法,主要是將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 2012-03-19 16:52:01

+0

這可能會幫助你http://stackoverflow.com/questions/3921616/java-leaking-this-in-constructor – Chikei 2012-03-19 16:52:36

+0

[Java - Leaking這在構造函數](http://stackoverflow.com/q/3921616/1048330) – tenorsax 2012-03-19 17:08:59

回答

0

我假設您可能會將您的JPanel擴展名添加到某個其他組件(例如JFrameJApplet,另一個JPanel等)。您提到您需要將該面板添加到該面板中的子組件以及該面板需要聆聽的「其他對象」之間有一點混合。將面板添加到附加JPanel擴展名到其包含的JFrame或其他父組件的位置附近,而不是在擴展的類定義之外,將面板添加到那些「其他對象」可能會更好。

但是,對於您的面板必須監聽的面板子組件,我認爲您所做的很好,只要這些子組件對您的JPanel擴展類定義以外的對象不可見。警告只是表明你正在做的事情可能是不安全的,但最終,當你的面板被垃圾收集時,它擁有的所有子組件,包括任何監聽器列表您的JPanel擴展名。因爲這個事實,我認爲把add*Listener(this)調用放在你的JPanel擴展的一個恰當命名的私有方法中,並從你的構造函數中調用它是沒有問題的。

另一個選擇是使用Eclipse,所以你不會再收到這些警告......(完全是開玩笑的)。

0

此警告的原因是您在構造函數未完成時傳遞此對象,因此對象未完全初始化。即使你在構造函數的末尾使用它,很有可能你的類被擴展了,並且有一個子類的構造函數會被執行。 在你的情況下(將對象註冊爲偵聽器)這是安全的,因爲Swing是單線程的,並且只有在初始化對象後纔會將事件傳遞給偵聽器。

+1

這是不好的編程,即使在單線程環境。 – 2012-03-19 18:02:51

2

我想知道這裏有沒有更大的問題 - 那就是要求你的班級做太多。一個班級應該有一個主要目的,一個觀點應該負責觀點,就是這樣。爲了讓它做模型或控制功能,並且你丟失了cohesion,可能會增加coupling,並冒着創造上帝對象的風險,如果不是不可能調試或擴展,那麼上帝對象也很難。所以說白了,你的GUI或者視圖類而不是也是監聽器類。換句話說,GUI類沒有很好的理由和很多不好的理由來實現一個監聽器接口。

最好的解決方案:不要讓你的GUI類實現監聽器。相反,要麼使用匿名內部類,要麼使用私有內部類,或者如果足夠複雜,或者您預計將來擴展和/或修改您的代碼,則需要獨立的偵聽器類。

+1

對於獨立偵聽器,[* package-private *](http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html)訪問可能會有用。 – trashgod 2012-03-19 18:48:36

+1

但是,如果匿名內部類的實例是在構造函數中創建的,則它不能解決泄漏'this'的問題。從現在'這個'隱含地泄漏,它只會使問題更難以發現。 – 2015-05-07 17:43:16

相關問題