25

I have following snippet of code:

public class Example {

private Integer threshold;

private Map<String, Progress> history;

protected void activate(ComponentContext ctx) {
    this.history = Collections.synchronizedMap(new LinkedHashMap<String, Progress>() {
        @Override
        protected boolean removeEldestEntry(Map.Entry<String, Progress> entry) {
            return size() > threshold;
        }
    });
  }
}

Theres is a cyclic dependency between anonymous LinkedHashMap class and Example class. Is this OK or not? Why not? Is it going to be nicely reclaimed by garbage collector?

4

5 に答える 5

22

これでいいですか?

これはまったく問題ありません。

thresholdはフィールドなので、匿名クラス内から問題なく参照できます。(thresholdローカル変数だった場合、(事実上) final でなければなりませんでした。)

クラス間の循環的な依存関係は一般的であり、依存関係グラフが小さい場合 (この場合のように)、問題は発生しません。yourLinkedHashMapが匿名クラスであるという事実は、ここでは問題になりません。

ガベージコレクターによってきれいに回収されるでしょうか?

メモリ リーク + 内部クラスに関して注意すべき唯一のことは、(非静的) 内部クラスがそれを囲むオブジェクトへの暗黙的な参照を持っていることです。これは、内部クラスのインスタンスを大量に作成すると、外部クラス オブジェクトのインスタンスがガベージ コレクションされることを期待できないことを意味します。

この場合の意味は、historyマップへの参照をリークすると、 のインスタンスはExampleGC されないということです。


関連ノート:

  • あなたがそれを使用していることを考えるとsynchronizedMap、マルチスレッドプログラムで作業しているようです。この場合、thresholdフィールドの同期と可視性の問題に注意する必要があります。

  • 可能であれば、thresholdフィールドを finalにするようにしてください

  • 別のオプションは、名前付きクラスを作成し、代わりにそのクラスにフィールドとしてLinkedHashMap含めることです。threshold

于 2015-06-08T12:12:34.987 に答える
2

循環依存自体は悪くありませんが、予期しないメモリ リークが発生する可能性があります。

あなたの例をそのままとると、あなたがやりたいことをするので、今は問題ありません。

ただし、あなた、または他の誰かがあなたのコードを変更してプライベートを公開した場合:

private Map<String, Progress> history;

すると、困ってしまうことがあります。内部クラスにはそれへの暗黙的な参照があるため、意図したかどうかにかかわらず、Example クラスへの参照も渡すことになります。

今すぐ直接引用することはできませんが、Steve McConnell はコードの完成版で循環依存関係をアンチパターンと呼んでいます。あなたはそこで読むことができます、または私はそれについてグーグルを推測します。これについて非常に詳細に読むことができます.

私が頭に浮かぶもう1つの問題は、オブジェクト間の非常に高いレベルの結合を作成しているため、循環依存関係を単体テストするのがかなり難しいことです。

一般に、循環リンク リストを実装するなど、非常に正当な理由がない限り、循環依存を避ける必要があります。

于 2015-06-08T12:21:21.947 に答える
1

私はあなたの解決策が好きではありません(これがうまくいくことに同意したとしても):

  1. クラス Example は Map を実装するか、LinkedHashMap を拡張する必要があります。これは、インスタンス変数のしきい値がそこで定義され、独自の定義で LinkedHashMap の概念を改良するためです。

  2. activate メソッドは LinkedHashMap も Map も洗練せず、マップの概念を使用するため、クラス Example は Map を実装したり、LinkedHashMap を拡張したりしないでください。

1+2 => 受胎の問題。

于 2015-06-08T12:38:38.657 に答える