He leído mucho últimamente sobre la fabricación de objetos inmutables siempre que sea posible. «Programación en Scala» enumera Tradeoffs objeto inmutable de la siguiente manera:.
Ventajas de objetos inmutables
- menudo más fácil razonar acerca porque no tienen complejo estado
- se pueden pasar libremente (sin hacer copias de defensa) a cosas que podrían tratar de modificarlos
- imposible que dos hilos accedan al mismo objeto inmutable a lo corrupto.
- Hacen claves de Hashtable seguros (si se pone un objeto mutable en una Hashtable, a continuación, cambiar de un modo que cambia su código hash, Hashtable ya no será capaz de utilizarlo como clave porque va a buscar ese objeto en el cubo mal y no encontrarlo).
Desventajas
- veces requerir un gráfico de objetos grandes a copiar (para crear una nueva versión modificada del objeto). . Esto puede provocar cuellos de botella de rendimiento y de recolección de basura
Para la mayoría de los propósitos, un objeto que representa un mes puede ser hecho inmutable – Febrero 2003 nunca llegarán a ser distinto de lo que es cualquier cosa. Pero un registro de usuarios no es inmutable. La gente se casa o cambiar su nombre por otros motivos. Números de teléfono, direcciones, color de pelo, altura, peso, y prácticamente todos los demás aspectos de una persona pueden cambiar. Sin embargo, la persona sigue siendo la misma persona. Esto es lo que el modelo claves sustitutas en una base de datos -. Que todo lo relacionado con un registro puede cambiar, sin embargo, todavía puede ser significativo el mismo registro
Para utilizar un objeto en una colección de hash con respaldo (en Java ), su código hash NO debe cambiar. La forma más sencilla de lograr esto es hacer que el código hash de un objeto persistente mutable su clave sustituta y para usar esa llave como una comparación primaria en el método es igual, así (ver mi post antiguo en iguales ejecución (), hashCode (), y compareTo ()).
Para hacer que un objeto inmutable, a veces se necesita un constructor de objeto mutable, como StringBuilder y String. StringBuilder permite cambiar el objeto tantas veces como desee, a continuación, obtener una versión inmutable llamando toString ()
. Este es limpio y seguro, pero tiene algunos pequeños costes en tiempo y la memoria (transformando el StringBuilder inmutable en un nuevo objeto String inmutable, a continuación, tirar el StringBuilder). Una alternativa que no he visto mucho es crear una interfaz inmutable, extender una interfaz mutable de la misma, y luego ampliar su objeto a partir de eso.
java.util.List
. Imagina cada interfaz o clase es en su propio archivo:.
/ / Todos los métodos inmutable-amistosos de java.util.List
/ / Interfaces como estos podrían ser instalados fácilmente en
/ / el marco colecciones Java existente
ImmutableList {
int size ();
estaVacia ();
contiene (Object o);
Iterator iterador ();
Object [] toArray ();
T [] toArray (T [] a);
containsAll (Collection c <>);
es igual a (Object o);
int hashCode ();
E get (int index);
int indexOf (Object o);
int lastIndexOf (Object o);
ListIterator ListIterator ();
ListIterator ListIterator ( int índice);
Lista subList ( int fromIndex, int toIndex);}
/ / Esta interfaz añade las mutators
interfaz pública extiende
ImmutableList { add (E e);
remove (Object o);
addAll (Collection extiende E> c) ;
addAll ( int índice, Collection < extiende E> c);
removeAll (Collection <> c);?
retainAll (<> Collection c);
clear ();
conjunto E ( int índice, elemento E);
void add ( int índice, elemento E);
E remove ( int índice);}
implementos Lista {
/ / tal como es ahora ...
}
public class
MyClass {algunMetodo (ils ImmutableList ) {
/ / no se puede cambiar la lista span>
}
public void estática main (String [] args) {
Lista myStrings = nueva ArrayList ();
myStrings.add ("hola");
myStrings.add ("mundo");
algunMetodo (myStrings);
/ / Totalmente seguro:
System.out.println (myStrings.get (1));}
}
Esto no resuelve el problema de pasar una lista de código no confiable existente que podría tratar de cambiarlo. También no impide que el código de llamada modifiquen myStrings
de un hilo separado mientras algunMetodo ()
está trabajando en ello. Pero sí proporciona una forma (en el futuro) por un método como algunMetodo ()
para declarar que no puede modificar la lista. El programador de algunMetodo ()
no puede compilar su código si ella trata de modificar la lista (así, sin recurrir a la reflexión).