質問

わかります 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>() );

は1つが、例えば、Set又はUnsupportedOperationExceptionをコールしようとした場合fixed.add()をスローしますfixed.remove()のインスタンス作成 - オブジェクト自体がその内部状態を保護し、変更されてからそれを防止するに

完全酒の場合:

private final Set<String> fixed = Collections.unmodifiableSet( new HashSet<String>() );

は、その内部状態を変更することができませんSetのインスタンスを作成し、またfixedにしかそのセットのインスタンスを指すことを意味します。

finalはプリミティブの定数を作成するために使用することができるという理由は、値を変更することができないという事実に基づいています。変更することはできませんアドレスを含む変数 - ちょうど参照した上でそのfixedを覚えておいてください。まあ、プリミティブの、例えばます。

private final int ANSWER = 42;

ANSWERの値はANSWERを変更することはできませんので42は、それだけで今までに値42を持つことになります。

すべてのラインをぼかし例は、このようになります:

private final String QUESTION = "The ultimate question";

上記のルールに従って、QUESTIONは「究極の質問」を表すStringのインスタンスのアドレスが含まれ、そのアドレスを変更することはできません。ここで覚えておくべき事はそのString自体は不変である - あなたはそれを変更Stringのインスタンスに何もできないし、そうでない場合(などreplacesubstring、など)、そうであろう任意の操作を参照し、全く異なるのを返します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();

または 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されていないとの参照の他の目的に再割り当てすることはできませんます。

( - スタイルC ++)final

constではありません。 C ++とは異なり、Javaはconst-方法またはそのようなものを持っていない、とオブジェクトを変更することができます方法はfinalの参照を経由して呼び出すことができます。

Collections.unmodifiable*は(だけではなく、コンパイル時に実行時に)強制ラッパーコレクションの読み取り専用らしです心配ます。

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を入れて、新しい基準(wrapperSet)に割り当てられます。

Set<String> wrapperSet=Collections.unmodifiableSet(orginalSet);

wrapperSetを印刷します。そう、それはactualSet値を持つことになります。

System.out.println(wrapperSet);   //[aaa, bbb]

wrapperSet上の一つの要素を追加/削除しようとすることができます。

wrapperSet.remove("aaa");   //UnSupportedOperationException 

actualSetに1つの以上の要素を追加します。

    actualSet .add("ccc");

印刷actualSetwrapperSet。両方のセットの値は同じです。あなたが追加した場合ので、/変更が同様に設定されたラッパーに反映される実際のセット上の任意の要素を削除します。

    System.out.println(actualSet);  //[aaa, ccc, bbb]
    System.out.println(wrapperSet);  // [aaa, ccc, bbb]

使用方法:

このCollections.unmodifiableSet(Set<? extends T>)は、任意のオブジェクトのセットのgetterメソッドの変更を防ぐために使用されます。しましょう。

public class Department{

    private Set<User> users=new HashSet<User>();

    public Set<User> getUsers(){
        return Collections.unmodifiableSet(users); 
    }
}

できることとできないことを要約すると、次のようになります。

準備:

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

参照による最終的なものであり、コレクションによる変更はできません。

privatefinal Setwords = Collections.unmodifiableSet(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
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top