1

私は、Javaメンバー変数と、到達可能リスペクトでのその宣言クラスについて混乱しています。まあ言ってみれば、

  1. TestPクラスには、TestCタイプのメンバー変数c1があります。
  2. メインクラスにはTestPpへの参照と、p.c1への別の参照があります。(makeP()
  3. しかし、p1参照が削除された後(clearP())、

p1.c1に到達可能であっても、p1はガベージコレクションされます。

証明することは、c1がいくつかのメソッドをオーバーライドする場合(または単に括弧を開閉する場合でも)、p1はガベージコレクションされないということです。c1がTestP領域を使用しているためだと思いますが、明確な説明をいただければ幸いです。

public class Main {
    TestP p;
    TestC c;
    void makeP { p = new TestP(); c = p.c1; }
    void clearP { p = null; }
}

public class TestP {
    public TestC c1;

    public TestP() {
        c1 = new TestC(); // TestP will be garbage-collected.
        // c1 = new TestC() {}; // TestP will not be garbage-collected.
    }
    ...
}

public class TestC {
    public TestC() {}
}
4

1 に答える 1

1

のインスタンスTestPは、参照がない場合にのみガベージ コレクションできます。匿名の内部クラス (または任意の内部クラス) のインスタンスには、その外側のインスタンスへの参照である非表示のメンバーがあります。つまり、で作成されたオブジェクト

c1 = new TestC() {};

TestPこのステートメントが実行されたコンストラクターのオブジェクトへの参照が含まれています。つまり、c1実際には次のようなクラスのインスタンスを指します。

class TestP$1 extends Test {
    private TestP $outer;

    TestP$1(TestP outer) {
        this.$outer = $outer;
    }
}

コンストラクターの引数とメンバー変数はコンパイラーによって隠されていますが、存在しています。

このような状況では、 の匿名サブクラスのインスタンスによって、 のTestインスタンスTestPが収集されなくなります。

于 2013-03-16T04:59:12.963 に答える