48

私が書いたら

List<Integer> a1 = Arrays.asList(1, 2, 3);
List<Integer> a2 = Collections.unmodifiableList(a1);

a2読み取り専用ですが、書き込むと

a1.set(0,10);

その後a2も変更されます。

API で次のように指定されている場合:

指定されたコレクションの変更不可能なビューを返します。このメソッドにより、モジュールはユーザーに内部コレクションへの「読み取り専用」アクセスを提供できます。

では、元のコレクションを変更すると、コピー先のコレクションも変更されるのはなぜですか?

意味を誤解したのかもしれません。もしそうなら、そのコレクションの防御的なコピーを書く方法は何ですか?

4

9 に答える 9

55

はい、あなたはそれを正しく理解しました。によって返されるオブジェクトをumodifiableCollection直接変更することはできませんが、他の手段で変更することができます (事実上、内部コレクションを直接変更することによって)。

何かが内部リストにアクセスできる限り、「変更不可能な」コレクションは変更される可能性があります。

そのため、通常、変更不可能なコレクションを構築し、内部リストに何も到達できないようにします。

Collection<Integer> myUmodifiableCollection = Collection.umodifiableCollection(Arrays.asList(1, 2, 3));

Listcreated byへの参照を取得するものは何もないためasList、これは真に変更不可能なコレクションです。

このアプローチの利点は、元のコレクション/リストをまったくコピーする必要がないことです。これにより、メモリと計算能力の使用が回避されます。

Guavaは、(通常はソースをコピーすることによって) 真の不変コレクションを提供するImmutableCollectionクラス (および などのそのサブクラスImmutableList) を提供します。

于 2013-02-27T11:39:41.067 に答える
12

意味を誤解したのかもしれません。もしそうなら、そのコレクションの防御的なコピーを書く方法は何ですか?

通常、次のように使用します。

private List<Integer> a1 = Arrays.asList(1, 2, 3);

public List<Integer> getUnmodifiable() {
    return Collections.unmodifiableList(a1);
}

クラスの内部にアクセスできない (つまり、プライベート変数にアクセスできない) 呼び出しgetUnmodifiable a1行った人は、返されたリストを変更できません。

于 2013-02-27T11:38:18.237 に答える
1

アイデアは、を介してリストを変更できないということですa2

リストを変更すると、a1実際に表示される内容が変更されますa2- これは意図されたものです。

リストにアクセスするためのパブリックな方法がないだけa1で、必要なものが必要です:)

于 2013-02-27T11:37:21.777 に答える
1

APIは、コレクションが内部ではない場合、内部コレクションと言っています

重要なのは、クラスにプライベート リストがあり、そのリストの gettet がある場合、getter の呼び出し元がリストを変更できないようにしたい場合があるということです。それ以外の場合、返されるリストは内部/プライベート リストへの参照にすぎないため、その内容を変更できます。

于 2013-02-27T11:37:44.730 に答える
1

ステートメント:

Collections.unmodifiableList(a1);

修飾子メソッドが throw をスローする元のコレクションのラッパーを返しますUnsupportedOperationException

ラッパーはリードスルーです。つまり、 を変更するa1と、ラップされたコレクションに変更が反映されますa2

于 2013-02-27T11:40:08.600 に答える
0

a1a2同じデータ (メモリ) を参照します。

変更できない部分は、a2エントリとしてのみ付属しています。

a2メソッドがべき等であると予想されるメソッドに渡す場合は、イメージングします。そのような場合a2に役立ちます。

要約すると、a2ポインターを使用してデータを変更することはできません。

于 2013-02-27T11:40:01.627 に答える