Pergunta

Eu posso ver que retornos Collections.unmodifiableSet uma visão não modificável do conjunto dado, mas eu não entendo por que não podemos simplesmente usar o modificador final para alcançar este objetivo.

No meu entendimento, final declara uma constante: algo que não pode ser modificado. Assim, se um conjunto é declarada como uma constante, então ele não pode ser modificado:. Nada pode ser removido do conjunto e nada pode ser acrescentado

Por que precisamos Collections.unmodifiableSet?

Foi útil?

Solução

final declara uma referência de objeto que não pode ser modificado, por exemplo.

private final Foo something = new Foo();

cria um novo Foo e coloca a referência no something. Depois disso, não é possível something alter para apontar para uma instância diferente do Foo.

Este não impedir a modificação do estado interno do objeto. Eu ainda pode chamar quaisquer métodos em Foo não são acessíveis ao âmbito relevante. Se um ou mais desses métodos modifica o estado interno do objeto, então final não vai impedir isso.

Como tal, o seguinte:

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

não criar um Set que não pode ser adicionado ou de outra forma alterada; isso significa apenas que fixed só vai referenciar essa instância.

Por outro lado, fazendo:

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

cria uma instância de um Set que vai jogar UnsupportedOperationException se alguém tenta fixed.add() chamada ou fixed.remove(), por exemplo -. O objeto em si vai proteger seu estado interno e impedir que ele seja modificado

Para sermos mais completos:

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

cria uma instância de um Set que não vai permitir que o seu estado interno que ser mudado, e também significa que fixed só nunca irá apontar para uma instância desse conjunto.

A razão que final pode ser usado para criar constantes de primitivos é baseado no fato de que o valor não pode ser alterado. Lembre-se que fixed acima foi apenas uma referência - uma variável que contém um endereço que não pode ser alterado. Bem, para primitivos, por exemplo.

private final int ANSWER = 42;

o valor de ANSWER é que 42. Desde ANSWER não pode ser alterado, ele só vai ter o valor 42.

Um exemplo que borra todas as linhas seria esta:

private final String QUESTION = "The ultimate question";

De acordo com as regras acima, QUESTION contém o endereço de uma instância de String que representa "A pergunta final", e esse endereço não pode ser alterado. A coisa a lembrar aqui é que String si é imutável - você não pode fazer nada para uma instância de String que muda-lo, e quaisquer operações que de outra forma fazê-lo (como replace, substring, etc.) referências de retorno para totalmente diferente instâncias de String.

Outras dicas

final só garante que o referência para o objeto a variável representa não pode ser alterado ele não faz nada para a instância do objeto e sua mutabilidade.

final Set s = new Set(); apenas garante que você não pode fazer s = new Set(); novamente. Não faz o conjunto não modificável, que se fez não se podia acrescentar nada para ele, para começar. Então, para deixar bem claro, final afeta somente a variável referência não o objeto os pontos de referência para.

Eu posso fazer o seguinte:

final List<String> l = new ArrayList<String>();
l.add("hello");
l.add("world");
l.remove(0);

mas não posso fazer isso.

l = new ArrayList<String>();

novamente por causa da final eu não posso modificar o que as variáveis ??pontos l de.

Você tem que fazer uma das três coisas a seguir para fazer uma coleção thread-safe recipiente.

java.util.Collections.syncronizedXXX();

ou

java.util.Collections.unmodifiableXXX();

ou usar um dos recipientes apropriados a partir java.util.concurrency.* package.

se eu tivesse um objeto Person e fez final Person p = new Person("me"); isso significa que eu não posso Reassign p para apontar para outro objeto Person. Eu ainda posso fazer p.setFirstName("you");

O que confunde a situação é que

final int PI = 3.14;
final String greeting = "Hello World!";

olhar como const em C ++, quando na verdade os objetos que eles apontam para são imutáveis ??/ unmodifiable por natureza. Recipientes ou objetos com métodos modificadores que podem alterar o estado interno do objeto não são const apenas o referência a esses objetos são final e não pode ser transferido para referência outro objeto .

final não é (C ++ - estilo) const. Ao contrário de C ++, Java não tem const-métodos ou qualquer coisa assim, e métodos que podem mudar o objeto pode ser chamado através de uma referência final.

Collections.unmodifiable* é um wrapper que impõe (em tempo de execução apenas, não em tempo de compilação) a read-only-ness para a colheita em causa.

O Collections.unmodifiableSet(Set<? extends T>) criará invólucro sobre o conjunto original. Este conjunto invólucro não pode ser modificado. mas ainda o conjunto original pode ser modificado.

Exemplo:

 Set<String> actualSet=new HashSet<String>(); //Creating set

A adição de alguns elementos

actualSet.add("aaa");
actualSet.add("bbb");

Impressão acrescentou elementos

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

Coloque o actualSet em conjunto unmodifiable e atribuído a nova referência (wrapperSet).

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

Imprimir o wrapperSet. por isso vai ter Valores actualSet

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

vamos tentar remover / adicionar um elemento em wrapperSet.

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

Adicionar mais um elemento em actualSet

    actualSet .add("ccc");

actualSet Imprimir e wrapperSet. ambos valores conjuntos são iguais. Então, se você adicionar / remover quaisquer elementos no conjunto real as mudanças serão refletidas no set invólucro também.

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

Uso:

Esta Collections.unmodifiableSet(Set<? extends T>) é usado para impedir a modificação do método getter do Conjunto de qualquer objeto. vamos dizer

public class Department{

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

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

resumir que podemos fazer e não pode:

Preparação:

private Set<String> words = new HashSet<>(Arrays.asList("existing word"));

final por referência

private final Set<String> words = new HashSet<>();

pode :

words.add("new word");

não pode :

words = new HashSet<>(); //compilation error

final por referência e não modificável pela coleção.

Definir palavras finais privados = Collections.unmodifiableSet (palavras);

pode :

String word = words.iterator().next();

não pode :

words = new HashSet<>(); // compilation error
words.add("new word"); // runtime error UnsupportedOperationException

final por referência e não modificável pela coleta, mas mútuo como objeto de coleção.

Mas se você tiver a coleção com mútua objetos você pode alterar o estado interno do objeto.

 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)));

ainda não pode

set = new HashSet<>(); // compilation error
set.add(new A(777)); // runtime error UnsupportedOperationException

Mas pode

 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
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top