2010-01-20 179 views
9

在對象生命週期的哪個點使用匿名內部類作爲PropertyChangeListener時,是否收集了類垃圾?包含類(SettingsNode)被回收後?我應該顯式移除包含類(SettingsNode)的終結器中的PropertyChangeListener嗎?Java - 匿名內部類生命週期

public class SettingsNode extends AbstractNode 
{ 
    public SettingsNode(Project project, ProjectSettings projectSettings) 
     throws IntrospectionException 
    { 
     // use an anonymous inner class to listen for changes 
     projectSettings.addPropertyChangeListener(ProjectSettings.PROP_NAME, 
      new PropertyChangeListener() 
      { 
       @Override 
       public void propertyChange(PropertyChangeEvent evt) 
       { 
        // handle event 
       } 
      }); 
    } 
} 
+0

根據提供的答案,匿名似乎不是此用例的最佳選項。我現在認爲一個實例內部類可能是一個更好的選擇,因爲我可以保存一個引用,並在將來的某個時刻調用removePropertyListener方法。 – javacavaj 2010-01-20 20:39:25

回答

7

像所有的對象,匿名內部類是符合垃圾收集時的最後一個引用不再引用它。我在這裏使用黃鼠狼的措辭,因爲Java不保證事情將會GC'd –唯一的保證是,只要有參考,它不會發生。

在這種特殊情況下,當projectSettings要麼是removePropertyListener(),要麼本身是垃圾收集。

因爲projectSettings引用了匿名內部類,並且由於內部類引用了它的包含類,這意味着包含類也將至少與內部類一樣長。

+0

儘管Java不保證*什麼時候會GC'd,我認爲你必須說它保證某些*將* GC'd如果替代是一個OutOfMemoryError。 – Yishai 2010-01-20 20:27:35

+0

現在你已經說過了,我不必再有了:)當然你是對的,謝謝你;但我希望我們的讀者都不會寫出依賴於此行爲的代碼。 – 2010-01-20 22:01:29

2

您正在將您正在創建的PropertyChangeListener類添加到projectSettings對象。只要projectSettings引用它,該PropertyChangeListener就不會被收集。

2

在示例中,您已經顯示設置節點和偵聽器都不能回收,直到項目設置被回收。

您將需要顯式刪除偵聽器,但您應該尋找比終結器更可靠的地方。

直到PropertyChangeListener被移除後,SettingsNode纔會被回收。聽衆使用匿名類會產生內存泄漏的常見原因。

編輯從亞歷克斯·B follwing問題:

如果projectSettings存在因爲你沒有對它的引用在註冊後無法刪除匿名監聽器的應用程序的生命。 由於創建了多個SettingsNode實例,因此它們將在構造函數中添加它們的偵聽器,但它們將永遠不會被刪除,因爲沒有人擁有對它們的引用。然後這將停止SettingsNodes被刪除以及聽衆對SettingsNode的引用

+0

@Aaron:你能否舉一個例子說明會發生內存泄漏? – 2010-01-20 20:13:44

+0

@Alex:如果在不再需要'SettingsNode'時不刪除監聽器,那麼問題中的代碼實際上已經是內存泄漏的示例。看到卡爾的答案解釋了這種情況。 – x4u 2010-01-20 20:22:38

0

內存泄漏的典型場景。不會推薦最終確定,因爲它可能會延遲GC。您可能會公開清理功能或覆蓋處理和取消註冊。

真的很驚訝爲什麼swing沒有建立在弱聽者註冊。可能你可以在source forge中嘗試一些開源代碼?

1

這個問題相當過時。

但是,我不同意這裏的大多數答案。

沒有必要明確地刪除監聽器。在這種情況下,內部類PropertyChangeListener對象將存活直到包含的實例SettingsNode被垃圾收集。

您實際上不能刪除PropertyChangeListener對象,因爲沒有爲它保留引用。

儘管PropertyChangeListener對象引用其包含的對象SettingsNode是對的,但並不妨礙包含對象被取消引用和垃圾回收。

一旦包含對象被取消引用,SettingsNode包含的所有對象就成爲一個「隔離島」。他們都將被垃圾收集。