Lo que hace Collections.unmodifiableSet () se puede hacer en Java?
-
19-09-2019 - |
Pregunta
Puedo ver que Collections.unmodifiableSet
devuelve una vista inmodificable del conjunto dado, pero no entiendo por qué no podemos sólo tiene que utilizar el modificador final
para lograr esto.
A mi entender, final
declara una constante: algo que no puede ser modificado. Por lo tanto, si un conjunto es declarado como una constante, entonces no puede ser modificado:. Nada puede ser retirado del conjunto y nada se puede añadir
¿Por qué necesitamos Collections.unmodifiableSet
?
Solución
final
declara una referencia de objeto que no se puede modificar, por ejemplo.
private final Foo something = new Foo();
crea un nuevo Foo
y coloca la referencia en something
. A partir de entonces, no es posible alterar something
a punto a una instancia diferente de Foo
.
Esto hace no impedirá que se modifique el estado interno del objeto. Todavía puedo llamar a cualquier método de Foo
no son accesibles para el ámbito correspondiente. Si uno o más de esos métodos modifica el estado interno de ese objeto, entonces final
no impedirá que.
Como tal, el siguiente:
private final Set<String> fixed = new HashSet<String>();
hace no crear un Set
que no puede ser añadido a o alterado de otra manera; sólo significa que fixed
referida solamente hacer referencia a esa instancia.
Por el contrario, haciendo:
private Set<String> fixed = Collections.unmodifiableSet( new HashSet<String>() );
Crea una instancia de un Set
que tirar UnsupportedOperationException
si se intenta llamar fixed.add()
o fixed.remove()
, por ejemplo -. El objeto mismo protegerá su estado interno y evitar que se modifique
Para completarlo:
private final Set<String> fixed = Collections.unmodifiableSet( new HashSet<String>() );
Crea una instancia de un Set
que no permitirá que su estado interno a ser cambiado, y también significa que será fixed
sólo apuntan a una instancia de ese conjunto.
La razón de que final
se puede utilizar para crear constantes de primitivas se basa en el hecho de que el valor no se puede cambiar. Recuerde que fixed
anteriormente era sólo una referencia - una variable que contiene una dirección que no se puede cambiar. Bueno, para los primitivos, por ejemplo.
private final int ANSWER = 42;
el valor de ANSWER
es que 42. Desde ANSWER
no se puede cambiar, será sólo tenga el valor 42.
Un ejemplo que difumina todas las líneas sería la siguiente:
private final String QUESTION = "The ultimate question";
Según las reglas anteriores, QUESTION
contiene la dirección de una instancia de String
que representa "La última pregunta", y que la dirección no se puede cambiar. Lo que hay que recordar aquí es que String
sí es inmutable - no se puede hacer nada para una instancia de String
que cambia, y cualquier operación que de otro modo de hacerlo (como replace
, substring
, etc.) devolver referencias totalmente diferente casos de String
.
Otros consejos
final
sólo garantiza que el referencia para el objeto representa la variable no se puede cambiar que no hace nada por la instancia del objeto y su mutabilidad.
final Set s = new Set();
simplemente garantiza que no puede hacer s = new Set();
nuevo. No tiene el conjunto no se puede modificar, si lo hizo no se podía añadir nada a ella, para empezar. Así que para que sea realmente claro, final
sólo afecta a la variable referencia no el objeto de los puntos de referencia a.
Puedo hacer lo siguiente:
final List<String> l = new ArrayList<String>();
l.add("hello");
l.add("world");
l.remove(0);
pero no puedo hacer esto.
l = new ArrayList<String>();
nuevo debido a la final
no puedo modificar lo que los puntos de variable de l a.
que tiene que hacer una de las siguientes tres cosas para hacer un hilo de deposito de seguridad.
java.util.Collections.syncronizedXXX();
o
java.util.Collections.unmodifiableXXX();
o
utilice uno de los recipientes apropiados de java.util.concurrency.* package
.
si tuviera un objeto Person
e hice final Person p = new Person("me");
que significa que no puede reasignar p
para apuntar a otro objeto Person
. Todavía puedo hacer p.setFirstName("you");
Lo que confunde la situación es que
final int PI = 3.14;
final String greeting = "Hello World!";
parecerse const
en C ++, cuando en realidad los objetos a los que apunten son inmutables / inmodificable por naturaleza. Contenedores u objetos con métodos de mutador que pueden alterar el estado interno del objeto no se const
sólo el referencia a esos objetos son final
y no pueden ser reasignados a referencia otro objeto .
final
no es (C ++ - estilo) const
. A diferencia de C ++, Java no tiene const
-métodos ni nada de eso, y los métodos que pueden cambiar el objeto puede ser llamado a través de una referencia final
.
Collections.unmodifiable*
es una envoltura que hace cumplir (en tiempo de ejecución solamente, no en tiempo de compilación) el de sólo-dad leer para la recogida en cuestión.
El Collections.unmodifiableSet(Set<? extends T>)
creará envoltorio en el conjunto original. Este sistema de la envoltura no se puede modificar. pero aún así el conjunto original puede ser modificado.
Ejemplo:
Set<String> actualSet=new HashSet<String>(); //Creating set
Adición de algunos elementos
actualSet.add("aaa");
actualSet.add("bbb");
Prensa añadió elementos
System.out.println(actualSet); //[aaa, bbb]
Ponga la actualSet
en conjunto inmodificable y asignado a la nueva referencia (wrapperSet
).
Set<String> wrapperSet=Collections.unmodifiableSet(orginalSet);
Imprimir el wrapperSet. por lo que tendrán valores actualSet
System.out.println(wrapperSet); //[aaa, bbb]
Vamos a tratar de eliminar / añadir un elemento de wrapperSet
.
wrapperSet.remove("aaa"); //UnSupportedOperationException
Añadir un elemento más en actualSet
actualSet .add("ccc");
Imprimir actualSet
y wrapperSet
. ambos valores conjuntos son iguales. así que si usted agrega / eliminar los elementos en conjunto real los cambios se reflejarán en la envoltura de establecer también.
System.out.println(actualSet); //[aaa, ccc, bbb]
System.out.println(wrapperSet); // [aaa, ccc, bbb]
Uso:
Esta Collections.unmodifiableSet(Set<? extends T>)
se utiliza para evitar la modificación del método de obtención del Conjunto de cualquier objeto. Digamos
public class Department{
private Set<User> users=new HashSet<User>();
public Set<User> getUsers(){
return Collections.unmodifiableSet(users);
}
}
resumir que podemos hacer y no hacer lo siguiente:
Preparación:
private Set<String> words = new HashSet<>(Arrays.asList("existing word"));
final por referencia
private final Set<String> words = new HashSet<>();
puede
words.add("new word");
no pueden
words = new HashSet<>(); //compilation error
Finales por referencia y no modificables por colección.
Definición de palabras finales privadas = Collections.unmodifiableSet (palabras);
puede
String word = words.iterator().next();
no pueden
words = new HashSet<>(); // compilation error
words.add("new word"); // runtime error UnsupportedOperationException
Finales por referencia y no modificables por colección pero mutuos como objeto de colección.
Pero si tiene la colección con mutua objetos se puede cambiar el estado interno de ese 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)));
Todavía no puede
set = new HashSet<>(); // compilation error
set.add(new A(777)); // runtime error UnsupportedOperationException
Pero puede
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