2014-09-30 191 views
0

一個代碼示例:對象的破壞時,子對象引用父對象

public class Parent{ 
    public void someMethod(){ 
    //start of some sort of loop 
    Child child = new Child(this); 

    //do something 
    //replaces reference from old child to new child 
    child = new Child(this); 
    //repeats loop 
    } 
} 

public class Child{ 
    Parent parent; 
    public Child(Parent parent){ 
    this.parent = parent; 
    } 
} 

從我的理解一個對象的生命週期,如果一個對象將被不再被引用,那麼這將是資格GC,比如當孩子的引用被改變爲引用一個新的第二個孩子對象時。

但是如果每個Child對象都有一個對創建它的對象的引用(如上所述),在這種情況下,一旦它不再被它的父對象引用,它有資格使用gc嗎?

如果不是,我該如何寫它,以便它?

回答

0

如果類A的實例具有對類B的實例的引用並且該類B的實例具有對類A的相同實例的引用,則只要這些引用存在,兩者都不符合GC的條件。

順便說一句,在你的例子中,Child實例被分配給Parent類中的一個本地方法變量,所以一旦該方法完成,Child實例將符合GC的條件,無論它是否擁有引用到創建它的父實例。

現在,如果您將Child實例引用存儲在Parent類的成員中,那麼您將擁有循環引用。然後,如果停止Parent實例的代碼將失去對Parent實例的所有引用,則循環引用永遠不會被刪除,因此這兩個對象都不符合GC的條件。

考慮這個〔實施例:

public class Parent{ 
    private Child child; 
    public Parent { 
     child = new Child(this); 
    } 

    public static void main (String[] args) 
    { 
     while (true) { 
      parent = new Parent(); 
     } 
    } 
} 

public class Child{ 
    Parent parent; 
    public Child(Parent parent){ 
     this.parent = parent; 
    } 
} 

在這裏,主要方法的無限循環將在每次迭代創建父母與子女的新實例,將永遠有資格GC,所以它最終將耗盡內存。

+0

哦,是的,我用這個新的父(),我編輯了一個錯字。但是,我將如何從子類刪除對父實例的引用?我應該做一個removeParent方法,並在裏面把家長參考爲空? – Imp 2014-09-30 05:16:36

+0

在上面的例子中,Parent沒有引用Child;一個children變量是someMethod()方法內的局部變量。 – Marco 2014-09-30 05:22:52

+0

@Nonexistent如果您有一個對Child實例的引用,並且在Child類中有一個使Parent引用無效的方法,則可以清除該引用。但是,如果您沒有對Child實例的引用,則無法執行此操作。 – Eran 2014-09-30 05:27:38

0

在您的someMethod()中,您正在創建兩個實例的類Child;它們都指向相同的Parent這一事實與您創建的第一個實例一旦被取消引用(最終)GC'd(當您重新指定child變量並創建新的Child對象的實例)。在實踐中,並不是那麼直接 - GC過程經歷了幾個階段(您可能想了解有關Tenured,Eden和Survivor階段的內容)。

0

根據this answer

Java的GC考慮對象的「垃圾」,如果他們不到達通過 鏈開始在垃圾收集根,所以這些對象將 被收集。即使對象可能互相指向以形成一個循環,但如果它們從根部切斷,它們仍然是垃圾。

所以你不需要爲這個循環參考案例做任何特殊的事情。