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?

¿Fue útil?

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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top