書いたら
List<Integer> a1 = Arrays.asList(1, 2, 3);
List<Integer> a2 = Collections.unmodifiableList(a1);
a2
は読み取り専用ですが、書き込む場合
a1.set(0,10);
a2
も変更されます。
APIの場合:
指定されたコレクションの変更不可能なビューを返します。このメソッドにより、モジュールはユーザーに内部コレクションへの「読み取り専用」アクセスを提供できます。
次に、元のコレクションを変更すると、ターゲットコピーされたコレクションも変更されるのはなぜですか?
たぶん私はその意味を誤解したのでしょうか、もしそうならそのコレクションの防御的なコピーを書く方法は何ですか?
はい、あなたはそれを正しく理解しました。アイデアは、umodifiableCollection
によって返されるオブジェクトを直接変更することはできませんが、他の方法で変更することができるということです(内部コレクションを直接変更することにより効果的に)。
何かが内部リストにアクセスできる限り、「変更できない」コレクションは変更できます。
そのため、通常は変更不可能なコレクションを作成し、内部リストに何もアクセスできないようにします。
Collection<Integer> myUmodifiableCollection = Collection.umodifiableCollection(Arrays.asList(1, 2, 3));
List
によって作成されたasList
への参照を取得するものはないため、これは本当に変更不可能なコレクションです。
このアプローチの利点は、元のコレクション/リストをまったくコピーする必要がないことです。これにより、メモリと計算能力の使用が回避されます。
Guava は、真の不変コレクションを提供する ImmutableCollection
クラス(および ImmutableList
などのサブクラス)を提供します(通常、ソースをコピーします)。
たぶん私はその意味を誤解したのでしょうか、もしそうならそのコレクションの防御的なコピーを書く方法は何ですか?
通常、次のように使用します。
private List<Integer> a1 = Arrays.asList(1, 2, 3);
public List<Integer> getUnmodifiable() {
return Collections.unmodifiableList(a1);
}
getUnmodifiable
andを呼び出す人は、クラスの内部にアクセスできません(つまり、プライベート変数a1
にアクセスできません)、できません返されたリストを変更します。
ステートメント:
Collections.unmodifiableList(a1);
修飾子メソッドがUnsupportedOperationException
をスローする元のコレクションのラッパーを返します。
ラッパーはリードスルーです。つまり、a1
、変更はラップされたコレクションに反映されますa2
。
a1
可変で、グアバなしで不変のコピーを作成します。これはあなたがそれを行うことができる1つの方法です。
List<Integer> a1 = Arrays.asList(1, 2, 3);
List<Integer> a2 = Collections.unmodifiableList(new ArrayList<>(a1));
a2
を使用してリストを変更することはできません。
a1
リストを変更すると、実際にa2
に表示されるものが変更されます-これは意図したものです。
リストa1
にアクセスするための公開された方法を持ってはいけません。
aPIはそれを言う内部コレクションあなたの場合、コレクションは内部ではない
ポイントは、クラスにプライベートリストがあり、そのリストのgettetである場合、ゲッターの呼び出し元が、変更できないリストを返す必要がある場合にリストを変更できないようにすることです。それ以外の場合、返されるリストは内部/プライベートリストへの単なる参照であるため、コンテンツを変更できます。
変更不可能で不変のリスト、つまり他のライブラリに依存しないソースリストの変更不可能なコピーが必要な場合は、これを試してください。
_Collections.unmodifiableList(Collections.list(Collections.enumeration(sourceList)))
_
Collections.list()
は、列挙から値をコピーします。