2012-05-25 17 views
50

¿Qué ventajas/inconvenientes podemos obtener haciendo que ArrayList (u otra colección) sea definitiva? Todavía puedo agregar nuevos elementos a ArrayList, eliminar elementos y actualizarlos. Pero, ¿qué efecto tiene hacer que sea final?¿Cuál es el sentido de ArrayList final?

+1

cuando una matriz se declara como final, el estado del objeto almacenado en la matriz se puede modificar. Debes hacerlo inmutable para no permitir modificaciones. –

Respuesta

103

Pero, ¿qué efecto tiene su final?

Esto significa que no se puede volver a enlazar la variable para que apunte a un diferente ejemplo colección:

final List<Integer> list = new ArrayList<Integer>(); 
list = new ArrayList<Integer>(); // Since `list' is final, this won't compile 

Como una cuestión de estilo, declaro mayoría de las referencias que no tiene intención de cambiar a medida final.

Todavía puedo agregar a ArrayList nuevos elementos, eliminar elementos y actualizarlo.

Si lo desea, puede impedir la inserción, eliminación, etc. mediante el uso de Collections.unmodifiableList():

final List<Integer> list = Collections.unmodifiableList(new ArrayList<Integer>(...)); 
+3

+1 El uso de campos finales puede mejorar la claridad ya que las clases pueden ser bastante largas. No uso métodos finales tanto como trato de separar métodos largos. –

13

Sólo significa que no se puede volver a asignar su referencia. Intentar hacer algo como lo siguiente dará lugar a un error del compilador.

final List<String> list = new ArrayList<String>(); 

list = new LinkedList<String>(); 
    ^
    Compiler error here 

Si realmente desea una lista inmutable, se debe utilizar el método Collections.unmodifiableList().

7

No podrá modificar su referencia utilizando new ArrayList por ejemplo.

1

Final es una palabra clave o reservada en java y se puede aplicar a variables miembro, métodos, clase y variables locales en Java. Una vez que haga una referencia final, no está permitido cambiar esa referencia y el compilador verificará esto y generará un error de compilación si prueba para reiniciar las variables finales en java.

3

No tiene efecto lo que puede hacer con ArrayList como observa con razón: el ArrayList en sí mismo todavía es mutable. Acabas de hacer la referencia inmutable.

Sin embargo, hacer una final de la variable tiene otros beneficios:

  • Previene la variable sea cambiada si se espera que permanezca constante. Esto puede ayudar a prevenir futuros errores.
  • Hacer variables final puede ayudar al compilador a realizar ciertas optimizaciones de rendimiento.

En general, cuantas más cosas hagas inmutables, mejor. Así que hacer referencias finales (incluso si son referencias a objetos mutables) es generalmente una buena idea.

1

No se puede volver a enlazar a una colección diferente como se dijo anteriormente.

Ejemplo: En conjunción con la implementación de listas inmutables, obtienes miembros seguros que puedes poner a disposición del público.

Ejemplo: Cuando usted confía en que la referencia no cambia lo que necesita final. Esto es cierto en los escenarios de sincronización, por ejemplo.

Puede haber muchos más ejemplos. Es un buen estilo declarar miembros finales si no tiene la intención de cambiar la referencia en absoluto.

5

Hacer la variable final se asegura de que no se puede volver a asignar esa referencia objest después de que se le asigna. Como mencionas, aún puedes usar esa lista de métodos para hacer cambios.

Si se combina la palabra clave final con el uso de Collections.unmodifiableList, que ge el comportamiento es probable que esté tratando de lograr, por ejemplo:

final List fixedList = Collections.unmodifiableList(someList); 

Esto tiene como consecuencia que la lista a la que apunta fixedList no puede ser cambiado Tenga cuidado sin embargo, que todavía se puede cambiar a través de la referencia someList (así que asegúrese de que está fuera del alcance después de este asignment.)

1

personalmente marca el campo colecciones de mis clases como final para guardar los usuarios de mi clase a partir de la comprobación si es nulo o no. Esto funciona porque, una vez que el valor ya está asignado a una variable final, nunca puede reasignarse a otro valor, incluido el nulo.

3

final tiene muchas consecuencias en virtud de múltiples subprocesos.

  1. JMM define claramente que la finalización de la inicialización de un campo final está garantizada.

Lo que no está claramente definido es:

  1. compiladores son libres de cambiar su orden a través de barreras de memoria.
  2. Los compiladores siempre pueden leer una copia en caché.
1

Para obtener una lista realmente inmutable, tendrá que hacer copias en profundidad de los contenidos de la lista. UnmodifiableList solo haría la lista de referencias algo inmutable. Ahora hacer una copia profunda de la lista o matriz será difícil para la memoria con el tamaño en crecimiento. Puede hacer uso de la serialización/deserialización y almacenar la copia profunda de la matriz/lista en un archivo temporal. El colocador no estaría disponible ya que el miembro varaible necesita ser inmutable. El getter serializaría la variable miembro en un archivo y luego lo desializaría para obtener una copia profunda. La serialización tiene una naturaleza innata de ir a las profundidades de un árbol de objetos. Sin embargo, esto garantizaría la inmutabilidad completa a algún costo de rendimiento.

package com.home.immutable.serial; 

import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
import java.util.ArrayList; 
import java.util.List; 

public final class ImmutableBySerial { 

    private final int num; 
    private final String str; 
    private final ArrayList<TestObjSerial> immutableList; 

    ImmutableBySerial(int num, String str, ArrayList<TestObjSerial> list){ 
     this.num = num; 
     this.str = str; 
     this.immutableList = getDeepCloned(list); 
    } 

    public int getNum(){ 
     return num; 
    } 

    public String getStr(){ 
     return str; 
    } 

    public ArrayList<TestObjSerial> getImmutableList(){ 
     return getDeepCloned(immutableList); 
    } 

    private ArrayList<TestObjSerial> getDeepCloned(ArrayList<TestObjSerial> list){ 
     FileOutputStream fos = null; 
     ObjectOutputStream oos = null; 
     FileInputStream fis = null; 
     ObjectInputStream ois = null; 
     ArrayList<TestObjSerial> clonedObj = null; 
     try { 
      fos = new FileOutputStream(new File("temp")); 
      oos = new ObjectOutputStream(fos); 
      oos.writeObject(list); 
      fis = new FileInputStream(new File("temp")); 
      ois = new ObjectInputStream(fis); 
      clonedObj = (ArrayList<TestObjSerial>)ois.readObject(); 

     } catch (FileNotFoundException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } catch (ClassNotFoundException e) { 
      e.printStackTrace(); 
     } finally { 
      try { 
       oos.close(); 
       fos.close(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 
     return clonedObj; 
    } 
} 
0

Esencialmente, lo que estás tratando de lograr aquí es hacer que la lista sea inmutable, supongo. Sin embargo, cuando marca la lista final de referencia, implica que la referencia no puede apuntar a ningún otro objeto de lista que no sea este.

Si quieres un (inmutable) ArrayList definitiva para ir Collections.unmodifaibleList método de utilidad Colecciones de clase (lista) en su lugar.

Cuestiones relacionadas