Pregunta

Las ventajas de los objetos inmutables en Java parecen claras:

  • estado consistente
  • seguridad automática del hilo
  • sencillez

Puede favorecer la inmutabilidad utilizando campos finales privados e inyección de constructor.

Pero, ¿cuáles son las desventajas de favorecer los objetos inmutables en Java?

es decir.

  • ¿Incompatibilidad con ORM o herramientas de presentación web?
  • ¿Diseño inflexible?
  • ¿Complejidades de implementación?

¿Es posible diseñar un sistema a gran escala (gráfico de objetos profundos) que utilice predominantemente objetos inmutables?

¿Fue útil?

Solución

Pero, ¿cuáles son las desventajas de favoreciendo los objetos inmutables en Java?incompatibilidad con ORM o web ¿Herramientas de presentación?

Los marcos basados ​​en la reflexión se complican por los objetos inmutables, ya que requiere inyección de constructor:

  • No hay argumentos predeterminados en Java, lo que nos obliga a proporcionar SIEMPRE todas las dependencias necesarias.
  • la anulación del constructor puede ser complicada
  • Los nombres de los argumentos del constructor generalmente no están disponibles a través de la reflexión, lo que nos obliga a depender del orden de los argumentos para la resolución de dependencias.

¿Complejidades de implementación?

Crear objetos inmutables sigue siendo una tarea aburrida;el compilador debe encargarse de los detalles de implementación, como en maravilloso

¿Es posible diseñar un sistema a gran escala (gráfico de objetos profundos) que utilice predominantemente objetos inmutables?

definitivamente sí;Los objetos inmutables son excelentes componentes básicos para otros objetos (favorecen la composición), ya que es mucho más fácil mantener la invariante de un objeto complejo cuando se puede confiar en sus componentes inmutables.El único verdadero inconveniente para mí es la creación de muchos objetos temporales (p. ej. La cadena concat era un problema en el pasado).

Otros consejos

Con la inmutabilidad, cada vez que necesite modificar los datos, es necesario crear un nuevo objeto. Esto puede ser costoso.

Imagínese necesidad de modificar un bit en un objeto que consume varios megabytes de memoria: lo que se necesita para crear instancias de un objeto completamente nuevo, asignar memoria, etc Si usted tiene que hacer esto muchas veces, la mutabilidad se vuelve muy atractiva

Si opta por la mutabilidad, encontrará que cada vez que necesite llamar a un método cuyo objeto no desea que cambie, o necesite devolver un objeto que es parte del estado interno, deberá adoptar una postura defensiva. Copiar.

Si realmente observa los programas que utilizan objetos mutables, encontrará que son propensos a "atacar" modificando:

  • objetos pasados ​​a constructores
  • objetos pasados ​​a métodos
  • objetos devueltos por métodos.

El problema no aparece muy a menudo porque la mayoría de los programas no cambian los datos (en realidad son inmutables porque nunca cambian).

Personalmente hago todo lo que puedo para durar.Probablemente tenga entre el 90% y el 95% de todas las variables (parámetros, locales, instancias, estáticas, excepciones, etc.) marcadas como finales.Hay algunos casos en los que tiene que ser mutable, pero en la gran mayoría de los casos no es así.

Creo que podría depender de tu enfoque.Si está escribiendo bibliotecas para que las utilicen terceros, piense en esto mucho más que si está escribiendo una aplicación que solo usted (o su equipo) mantendrá.

Creo que puedes escribir aplicaciones a gran escala utilizando objetos inmutables para la mayor parte del sistema sin demasiado dolor.

En el fondo, en el mundo real, el estado asociado con muchas identidades particulares cambiará. Si le pido lo que es "la posición actual de Buick de Joe", hoy en día puede ser que sea un lugar en Seattle, y mañana podría ser un lugar en Los Alamos. Sería posible definir y crear un objeto GeographicLocation cuyo valor será siempre representan la ubicación donde Joe Buick fue en algún momento en el tiempo y que nunca cambia - si hoy representa un lugar en Seattle, entonces siempre lo hará. Este tipo de objeto, sin embargo, no tendría identidad continua como "la ubicación actual de Buick de Joe".

También puede ser posible definir las cosas para que hay un objeto VehicleLocation que está conectado a Buick de Joe de tal manera que el objeto siempre representa "la ubicación actual de Buick de Joe". Tal objeto podría conserva su identidad como "la ubicación actual de Buick de Joe", incluso cuando el coche se mueve alrededor, pero no representaría una ubicación geográfica constante. La definición de "identidad" puede ser difícil si se tiene en cuenta el escenario en el que Joe vende su Buick a Bob y compra un Ford - si la pista de objetos "la ubicación actual de Joe Ford" o "la ubicación actual de Buick de Bob" - pero en muchos casos, estos problemas pueden ser evitados mediante el uso de un modelo de datos que garantiza que algunos aspectos de la identidad del objeto nunca cambiarán.

No es posible para todo lo que un objeto sea inmutable. Si un objeto es inmutable, entonces no puede tener una identidad inmutable que encapsula nada más allá de su estado actual. Si un objeto es mutable, sin embargo, puede tener una identidad inmutable cuyo significado trasciende su estado actual. En muchas situaciones, tener una identidad inmutable es más útil que tiene un estado inmutable, y en tales situaciones objetos mutables son casi esencial. Si bien es posible en algunos casos para "simular" objetos mutables por tener un objeto inmutable que buscar a través de la versión más reciente de un objetos inmutables para encontrar información que puede "cambiar" entre una versión y la siguiente, se acerca un tales son a menudo extremadamente ineficiente. Incluso si uno mágicamente podría recibir una vez por minuto un libro encuadernado que dio la ubicación de cada vehículo en todas partes, mirando hacia arriba "de Joe Buick" en el libro tomaría mucho más tiempo que simplemente pidiendo una "ubicación actual de Joe Buick" objeto que lo haría siempre saber dónde estaba el coche.

Más o menos, responde a su propia pregunta. La especificación JavaBean, no creo, menciona nada acerca de la inmutabilidad, sin embargo JavaBeans son el pan de cada día de muchos marcos de Java.

El concepto de tipos inmutables es algo raro que las personas utilizan de imperiosas estilos de programación. Sin embargo, para muchas situaciones inmutabilidad tiene grandes ventajas, que nombró los más importantes ya.

Hay buenas maneras de implementar árboles equilibrados inmutables, colas, pilas, Retiros de cola y otras estructuras de datos. Y, de hecho, muchos lenguajes de programación modernos / marcos sólo admiten cadenas inmutables debido a sus ventajas y algunas veces otros objetos.

Con un objeto inmutable, si el valor tiene que ser cambiado, entonces debe ser reemplazada por una nueva instancia. Dependiendo del ciclo de vida del objeto, reemplazándolo con una instancia diferente potencialmente puede aumentar el tiempo de recogida (largo) de basura tenured. Esto se hace más crítica si el objeto se mantiene en torno a la memoria el tiempo suficiente para ser colocado en la generación titular.

El problema en Java es que uno tiene que vivir con todos esos objetos, donde la clase se ve así:

class Mutable {
    State1 f1;
    MoreState f2;
    void doSomething() {  // mutate the state, but don't document it }
    void doSomethingElse()  /// mutate the state heavily, do not mention in doc
}  

(Nota de la interfaz Cloneable falta).

El problema con el recolector de basura no es uno tan grande hoy en día. de la máquina virtual están contentos con los objetos de vida cortos.

Los avances en la tecnología / compilador JIT harán posible que, tarde o temprano, para optimizar la creación de objetos intermedia temporal fuera. Por ejemplo:

BigInteger  three =, two =, i1 = ...;
BigInteger  i2 = i1.mul(three).div(two);  

El JIT podría notar que el i1.mul objeto intermedio (tres) se puede utilizar para el resultado final y llamar a una variante del método div que funciona en un acumulador mutable.

Funcional Java para alcanzar una respuesta completa a su pregunta.

La inmutabilidad, como cualquier otro patrón de diseño, sólo se debe utilizar cuando lo necesite. Usted da el ejemplo de hilo de seguridad: En una aplicación altamente roscado, se puede favorecer la inmutabilidad sobre el gasto adicional de lo que es hilo de seguridad usted mismo. Sin embargo, si su diseño requiere objetos para ser mutable, no salir de su manera de hacerlos inmutable, simplemente porque "es un patrón de diseño".

En cuanto a la gráfica, se puede optar por hacer sus nodos inmutable y dejar que otra clase cuidar de las conexiones entre ellos, o se puede hacer que un nodo mutable que se ocupa de sus propios hijos y tiene una clase de valor inmutable.

Probablemente el mayor costo de utilizar objetos immutabile en Java es que los futuros desarrolladores no se lo esperaban o se utilizan para ese estilo. Esperar a ninguno de los documentos en gran medida o ver una gran cantidad de objetos desovar compañeros mutables en el tiempo.

Una vez dicho esto, la única razón técnica real que ocurre para evitar los objetos inmutables es la rotación GC. Para la mayoría de las aplicaciones, no creo que esto es una razón de peso para evitarlos.

Lo más importante que he hecho con un ~ 90% objetos inmutables era un intérprete de esquema al estilo juguete, por lo que es ciertamente posible hacer proyectos Java complejas.

en los datos inmutables usted no cosas Fijar dos veces ... ver Haskell y Scala Vals (y clojure de cource) ...

Por ejemplo .. para una estructura de datos .. como un árbol, cuando se realiza la operación de escritura en el árbol, de hecho, va a añadir elementos fuera del árbol inmutable .. después de terminado .. el árbol y la rama son recombinado en un nuevo árbol .. así como esto se podría realizar lecturas simultáneas y escribe muy safelly ..

en el modelo tradicional, debe bloquear un valor de causa podría ser reseteado cualquier momento .. .. así que terminar con una zona de calor muy por threads..since actúan secuencialmente allí de todos modos ..

con los datos imuttable, usted no lo configura más de una vez .. es una forma totalmente nueva de la programación .. puede terminar usando un poco más de memoria .. pero paralelización es natural y sin dolor ..

Al igual que con cualquier herramienta, usted tiene que saber cuándo usarlo y cuándo no.

Al igual que Tehblanx señala que si desea cambiar el estado de una variable que contiene un objeto inmutable, usted tiene que crear un nuevo objeto, que puede ser costoso, especialmente si el objeto es grande y complejo. Absolutamente cierto, pero eso simplemente significa que usted tiene que decidir inteligentemente qué objetos deben ser mutable y que debería ser inmutable. Si alguien está diciendo que todos los objetos deben ser inmutables, bueno, eso es sólo una locura.

Me tiendo a decir que los objetos que representan un único "hecho" lógica debe ser inmutable, mientras que los objetos que representan múltiples hechos deben ser mutable. Al igual que, un entero o una cadena deben ser inmutables. Un objeto "Cliente" que contenga el nombre, la dirección, la cantidad, la fecha de la última compra, etc debe ser mutable. Por supuesto que puedo pensar inmediatamente en un centenar de excepciones a esta regla general. Una excepción que hago todo el tiempo es cuando tengo una clase que solo existe como un envoltorio para mantener una primitiva de algún caso en el que una primitiva no es legal, al igual que en una colección, pero tengo que actualizarlo constantemente.

En Java, un método no puede devolver varios objetos, como return a, b, c. Devolución de una matriz de objetos hace que el código feo. En esta situación, tengo que pasar objetos mutables con el método y dejar que cambiar los estados de estos objetos. Sin embargo, no sé si devolver varios objetos es un olor código o no.

La respuesta es ninguno. No hay buenas razones para ser mutable.

No ejecuta en problemas con un montón de marcos (o versiones marco) que requieren los objetos mutables con el fin de trabajar con ellos (primavera estoy evidente en su dirección). A medida que trabaja con ellos y los peces a través del código que va a sacudir el puño con furia que es necesario introducir la mutabilidad sucia en un bloque de otra manera gloriosa de código cuando se podría haber evitado fácilmente.

Estoy seguro de que hay casos de esquina limitadas (probablemente más hipotéticos que nada), donde la sobrecarga de la creación de objetos y la colección es uncceptable. Pero insto a las personas que hacen que este argumento para mirar a idiomas como el Scala, donde se incluyen las colecciones son inmutables por defecto y luego buscar en el grupo de rendimiento de aplicaciones críticas construido en la cima de ese concepto.

Esta es la hipérbole supuesto. En realidad, hay que ir con la inmutabilidad primero, ver si le causa ningún medibles problemas, si lo hace entonces introducir la mutabilidad, pero asegúrese de que puede demostrar que resuelve su problema. De lo contrario se acaba de crear responsabilidad por ningún beneficio. Al hacer esto, yo creo que usted encontrará casos objetivas para "complejidad de la implementación" y "inflexibilidad" muy difícil de hacer.

Algunas implementaciones de objetos inmutables tienen medios transaccionales para actualizar un objeto inmutable. De manera similar a la forma en bases de datos proporcionan los compromisos y retrotracciones seguras. Sin embargo, en aparente contraste con muchas de las respuestas aquí. Los objetos inmutables no se cambian. Una operación típica sería.

B = append(A,C)

B es un objeto nuevo. Al igual que A y C. No se hizo ninguna modificación a A o C. internamente una aplicación de color rojo árbol de negro hace que este tipo de semántica lo suficientemente rápido como para ser utilizable.

La desventaja es que no es tan rápido como hacer las operaciones en su lugar. Pero eso sólo se compara una única parte del sistema. Al evaluar las posibles desventajas que tenemos que mirar el sistema en su conjunto. Y yo personalmente no tengo una idea clara de todo el impacto. Aunque sospecho inmutabilidad gana al final.

Sé que algunos expertos sostienen hay contención en el nivel superior del árbol negro rojo. Y eso tiene un efecto negativo en throught-venta.

Mi mayor preocupación con las estructuras de datos inmutables es cómo guardar / reconstituir ellos. Es decir, si una clase tiene campos finales, no puedo instanciarlo y después define los campos correspondientes.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top