2012-03-19 9 views
7

Para hacer una clase inmutable lo que puedo hacer es:hacer una clase inmutable en java

1) Hacer una clase final
2) no proporcionan los emisores
3) marcar todas las variables como definitiva

pero si mi clase tiene otro objeto de alguna otra clase, entonces, somone puede cambiar el valor de ese objeto

class MyClass{ 
final int a; 
final OtherClass other 

MyClass(int a ,OtherClass other){ 
    this.a = a; 
    this.other = other; 
} 

int getA(){ 
    return a; 
} 

OtherClass getOther(){ 
    return other; 
} 

public static void main(String ags[]){ 
    MyClass m = new Myclass(1,new OtherClass); 
    Other o = m.getOther(); 
    o.setSomething(xyz) ; //This is the problem ,How to prevent this? 

} 
} 
+4

no escriba el método de configuración –

+0

@LuiggiMendoza, creo que Other/OtherClass está destinado a ser una clase que no controla. –

+3

Escribe un contenedor para la otra clase y crea getters solamente. – Nican

Respuesta

3

A) Hacer el OtherClass inmutable, así

o

B) no permiten el acceso directo al objeto OtherClass, en lugar proporcionando sólo captadores para actuar como un proxy.

Editar para añadir: Usted podría realizar una copia profunda de OtherClass y devolver una copia en lugar del original, pero que generalmente no es el tipo de comportamiento que se puede esperar en Java.

1

asumo OtherClass (por la forma de decirlo otro vez) está destinado a ser una clase que no controlas , o que tiene que tener un colocador.

Si no puede eliminar getOther, cámbielo a getOtherView y devuelva una vista de solo lectura de other. Habrá envoltorios para todos los métodos de obtención, pero no hay conjuntos.

1

Devuelve los clones profundos de tus captadores. Puede encontrar que esta no es una tarea fácil.

1

Todos los objetos a los que se hace referencia en la clase inmutable deben ser inmutables, o al menos encapsulados como privados y asegurarse de que no se modifiquen (no dentro de los métodos de su clase y definitivamente no desde el exterior). Por ejemplo, si usted tiene esta situación:

public class MyImmutable { 
    private MutableClass mutableObject; 
} 

... No se puede proporcionar el método getMutableObject(), ya que al hacerlo se abrirá la puerta a modificaciones fuera, así:

myImmutable.getMutableObject().setSomeAttribute(newValue); 

Como caso especial del anterior, todas las colecciones y/o mapas deben hacerse inmutables, con los métodos ummodifiableXXX() en la clase Collections.

1

no se puede (razonablemente) detener eso en java. si no tienes control sobre la otra clase, hay formas de lograr un comportamiento inmutable de manera efectiva, pero puede ser muy costoso en la práctica. básicamente, siempre debe devolver una copia de esa clase en cualquier valor de retorno de método público. (el jdk realmente tiene este problema con la clase TimeZone).

1

pero si mi clase tiene otro objeto de alguna otra clase, entonces, somone puede cambiar el valor de ese objeto ...

objetos de Java no son primitivos. Si marca una primitiva como final, entonces su valor no se puede cambiar una vez que se haya asignado. Sin embargo, los contenidos de los objetos no pueden ser definitivos, solo las referencias de los objetos pueden ser definitivas. Entonces no puedes hacer un objeto de esta manera.

Una solución podría ser abandonar todos los métodos setter/mutator que podrían cambiar los campos particulares del objeto y encapsularlos de manera que solo pueda acceder a ellos, no cambiarlos.

2

La inmutabilidad se considera mejor desde la perspectiva del usuario API. Por lo que su API objeto necesita para satisfacer las dos condiciones siguientes:

  1. hay forma de que un usuario externo para cambiar el valor del objeto
  2. Una garantía de que cada vez que el usuario lee o hace uso del valor del objeto en el futuro, se obtendrá el mismo resultado

nota importante: de hecho, es bien tener los datos mutables dentro de un objeto inmutable siempre que se comporta como un objeto inmutable desde la perspectiva del usuario de la API. Considere java.lang.String por ejemplo: aunque generalmente se considera como la clase inmutable definitiva, de hecho tiene un campo interno mutable para el almacenamiento en memoria caché de hashCode (¡no mucha gente sabe esto!).

Así que para abordar su pregunta, si desea contener otro objeto (mutable) dentro de un objeto inmutable, entonces normalmente tiene que hacer uno o más de los siguientes:

Garantía
  • que nadie más puede cambiar el valor del objeto mutable. Normalmente, esto significa garantizar que nadie más pueda tener una referencia al objeto mutable, por lo que esto solo suele ser posible si crea el objeto usted mismo en lugar de aceptar una referencia desde el exterior.
  • Tome una copia profunda defensiva del objeto mutable, y no entregue referencias a la nueva copia. Solo permita operaciones que lean la nueva copia en la API pública. Si necesita distribuir una referencia a este objeto, debe tomar otra copia defensiva (para evitar distribuir una referencia a la copia interna).
  • Utilice una envoltura inmutable para el objeto mutable. Algo así como Collections.unmodifiableList. Esto es útil si desea distribuir una referencia al objeto mutable interno, pero no desea correr el riesgo de que se modifique.

Todas estas soluciones son un poco hacky - una mejor solución en general es evitar el uso de objetos mutables dentro de objetos inmutables. A la larga, es un problema porque, tarde o temprano, se filtrará una referencia mutable y tendrás un error extremadamente difícil de encontrar. Usted es mejor avanzar hacia una jerarquía completa de objetos inmutables (el enfoque adoptado por idiomas como el Scala y Clojure)

+0

Casi cualquier objeto que contenga una colección de tamaño variable tendrá una matriz como almacén de respaldo, por lo que evitar completamente los objetos mutables anidados generalmente no es práctico (casi todo lo que se puede hacer con una matriz puede hacerse usando árboles inmutables, pero en muchos casos las matrices serán más que un orden de magnitud más rápidas). – supercat

1

Es posible crear la clase inmutable en Java siguientes maneras

1.Do no Proporcionar colocador métodos.

2.Haga que todos los campos sean como finales y privados.

3.Haga clase como final.

+0

solo es válido cuando los campos son inmutables. – KillBill

Cuestiones relacionadas