これは、指定されたセットの変更不可能なビューを返すことがわかりますが、これを実現するために修飾子をCollections.unmodifiableSet
使用できない理由がわかりません。final
私の理解ではfinal
、定数を宣言します:変更できないもの。したがって、セットが定数として宣言されている場合、それを変更することはできません。セットから何も削除できず、何も追加できません。
なぜ必要なのCollections.unmodifiableSet
ですか?
これは、指定されたセットの変更不可能なビューを返すことがわかりますが、これを実現するために修飾子をCollections.unmodifiableSet
使用できない理由がわかりません。final
私の理解ではfinal
、定数を宣言します:変更できないもの。したがって、セットが定数として宣言されている場合、それを変更することはできません。セットから何も削除できず、何も追加できません。
なぜ必要なのCollections.unmodifiableSet
ですか?
final
変更できないオブジェクト参照を宣言します。例:
private final Foo something = new Foo();
新しいFoo
を作成し、参照をに配置しsomething
ます。something
その後、の別のインスタンスを指すように変更することはできませんFoo
。
これは、オブジェクトの内部状態の変更を妨げるものではありません。Foo
関連するスコープにアクセスできるメソッドは、引き続き呼び出すことができます。これらのメソッドの1つ以上がそのオブジェクトの内部状態を変更する場合、それfinal
を防ぐことはできません。
そのため、次のようになります。
private final Set<String> fixed = new HashSet<String>();
追加または変更できないを作成しません。これは、そのインスタンスのみを参照することをSet
意味します。fixed
対照的に、次のことを行います。
private Set<String> fixed = Collections.unmodifiableSet( new HashSet<String>() );
またはを呼び出そうとするSet
とスローされるインスタンスを作成します。たとえば、オブジェクト自体がその内部状態を保護し、変更されないようにします。UnsupportedOperationException
fixed.add()
fixed.remove()
完全を期すために:
private final Set<String> fixed = Collections.unmodifiableSet( new HashSet<String>() );
Set
内部状態を変更できないaのインスタンスを作成します。これはfixed
、そのセットのインスタンスのみを指すことも意味します。
プリミティブの定数を作成するために使用できる理由final
は、値を変更できないという事実に基づいています。fixed
上記は単なる参照であり、変更できないアドレスを含む変数であることを忘れないでください。ええと、プリミティブの場合、例えば
private final int ANSWER = 42;
の値はANSWER
42ANSWER
です。変更できないため、値は42になります。
すべての線をぼかす例は次のとおりです。
private final String QUESTION = "The ultimate question";
上記のルールに従い、「究極の質問」を表すQUESTION
インスタンスのアドレスが含まれており、そのアドレスは変更できません。String
ここで覚えておくべきことは、String
それ自体が不変であるということです。それを変更するインスタンスに対しては何もできません。String
そうでなければ変更する操作(replace
、substring
など)は、のまったく異なるインスタンスへの参照を返しますString
。
final
変数が表すオブジェクトへの参照が変更できないことを保証するだけで、オブジェクトのインスタンスとその可変性に対しては何もしません。
final Set s = new Set();
二度とできないことを保証するだけですs = new Set();
。セットを変更できないようにするわけではありません。そもそも何も追加できなかった場合です。したがって、明確にするために、参照が指すオブジェクトではなく、変数参照final
にのみ影響します。
私は次のことができます:
final List<String> l = new ArrayList<String>();
l.add("hello");
l.add("world");
l.remove(0);
しかし、私はこれを行うことはできません。
l = new ArrayList<String>();
final
変数lが指すものを変更できないためです。
コレクションコンテナのスレッドを安全にするには、次の3つのいずれかを実行する必要があります。
java.util.Collections.syncronizedXXX();
また
java.util.Collections.unmodifiableXXX();
または、から適切なコンテナの1つを使用しjava.util.concurrency.* package
ます。
Person
オブジェクトがあり、それを実行した場合、別のオブジェクトを指すようにfinal Person p = new Person("me");
再割り当てすることはできません。私はまだすることができますp
Person
p.setFirstName("you");
状況を混乱させるのは
final int PI = 3.14;
final String greeting = "Hello World!";
C ++のようconst
に見えますが、実際には、それらが指すオブジェクトは本質的に不変/変更不可能です。オブジェクトの内部状態を変更できるミューテイタメソッドを持つコンテナまたはオブジェクトは、それらのオブジェクトへの参照const
だけではなく、別のオブジェクトを参照するために再割り当てすることもできません。final
元のCollections.unmodifiableSet(Set<? extends T>)
セットにラッパーを作成します。このラッパーセットは変更できません。ただし、元のセットは変更できます。
例:
Set<String> actualSet=new HashSet<String>(); //Creating set
いくつかの要素を追加する
actualSet.add("aaa");
actualSet.add("bbb");
追加された要素を印刷する
System.out.println(actualSet); //[aaa, bbb]
を変更不可能なセットに入れ、actualSet
新しいreference()に割り当てwrapperSet
ます。
Set<String> wrapperSet=Collections.unmodifiableSet(orginalSet);
wrapperSetを印刷します。actualSet
値があります
System.out.println(wrapperSet); //[aaa, bbb]
の1つの要素を削除/追加してみましょうwrapperSet
。
wrapperSet.remove("aaa"); //UnSupportedOperationException
にもう1つの要素を追加しますactualSet
actualSet .add("ccc");
印刷actualSet
してwrapperSet
。両方のセット値は同じです。したがって、実際のセットで要素を追加/削除すると、変更はラッパーセットにも反映されます。
System.out.println(actualSet); //[aaa, ccc, bbb]
System.out.println(wrapperSet); // [aaa, ccc, bbb]
使用法:
これ Collections.unmodifiableSet(Set<? extends T>)
は、任意のオブジェクトのSetのgetterメソッドの変更を防ぐために使用されます。言わせて
public class Department{
private Set<User> users=new HashSet<User>();
public Set<User> getUsers(){
return Collections.unmodifiableSet(users);
}
}
final
(C ++スタイル)ではありませんconst
。C ++とは異なり、Javaにはconst
-methodsなどがなく、オブジェクトを変更できるメソッドはfinal
参照を介して呼び出すことができます。
Collections.unmodifiable*
は、関連するコレクションの読み取り専用性を(コンパイル時ではなく実行時にのみ)強制するラッパーです。
できることとできないことを要約します。
準備:
private Set<String> words = new HashSet<>(Arrays.asList("existing word"));
private final Set<String> words = new HashSet<>();
できます:
words.add("new word");
できません:
words = new HashSet<>(); //compilation error
プライベートファイナルセットワード=Collections.unmodizableSet(words);
できます:
String word = words.iterator().next();
できません:
words = new HashSet<>(); // compilation error
words.add("new word"); // runtime error UnsupportedOperationException
ただし、相互オブジェクトを含むコレクションがある場合は、そのオブジェクトの内部状態を変更できます。
class A {
public int a; //mutable field. I can change it after initialization
public A(int a) {this.a = a;}
}
private final Set<A> set = Collections.unmodifiableSet(Arrays.asList(new A(25)));
まだできません
set = new HashSet<>(); // compilation error
set.add(new A(777)); // runtime error UnsupportedOperationException
しかし、できます
A custom = words.iterator().next(); //here custom.a = 25;
custom.a = 777; //here first element of **final, unmodifible** collection
//was changed from 25 to 777