O que Collections.unmodifiableSet () fazer em Java?
-
19-09-2019 - |
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
?
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.
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