que - Hacer objeto inmutable de Java
programaciĆ³n funcional inmutable (14)
Mi objetivo es hacer que un objeto Java sea inmutable. Tengo una clase Student
. Lo codifiqué de la siguiente manera para lograr la inmutabilidad:
public final class Student {
private String name;
private String age;
public Student(String name, String age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public String getAge() {
return age;
}
}
Mi pregunta es, ¿cuál es la mejor manera de lograr la inmutabilidad para la clase de Student
?
- Declare la clase como final para que no pueda extenderse.
- Haga que todos los campos sean privados para que no se permita el acceso directo.
- No proporcione métodos setter para variables
- Haga que todos los campos mutables sean definitivos para que su valor se pueda asignar solo una vez.
- Inicialice todos los campos mediante un constructor que realice una copia en profundidad.
- Realice la clonación de objetos en los métodos captadores para devolver una copia en lugar de devolver la referencia real del objeto.
Ampliando la respuesta un poco.
final
no es lo mismo que Immutable
pero puede usar final
para hacer que ciertas cosas sean inmutables si lo usa de ciertas maneras.
Ciertos tipos son inmutables, ya que representan valores invariables en lugar de objetos de estado variable. Las cadenas, números, etc. son inmutables. Al final, usualmente nuestros objetos se reducen a estructuras de datos que finalmente hacen referencia a valores inmutables, pero cambiamos las estructuras de datos asignando nuevos valores a los mismos nombres de campo.
Por lo tanto, para hacer que algo sea realmente inmutable, debes asegurarte de que el final se use por completo, hasta que llegues a cada campo y alcance cada valor en la base de tu árbol de composición. De lo contrario, algo podría cambiar debajo de tu objeto y no es completamente inmutable.
Aquí hay algunas reglas que ayudan a que una clase sea inmutable en Java: 1. El estado del objeto inmutable no se puede modificar después de la construcción, cualquier modificación debería dar como resultado un nuevo objeto inmutable. 2. Todos los campos de la clase Inmutable deben ser finales. 3. El objeto debe estar construido adecuadamente, es decir, la referencia del objeto no debe tener fugas durante el proceso de construcción. 4. El objeto debe ser final para restringir la subclase para alterar la inmutabilidad de la clase padre.
Ejemplo:
public final class Contacts {
private final String name;
private final String mobile;
public Contacts(String name, String mobile) {
this.name = name;
this.mobile = mobile;
}
public String getName(){
return name;
}
public String getMobile(){
return mobile;
}
}
Consulte este enlace: http://javarevisited.blogspot.in/2013/03/how-to-create-immutable-class-object-java-example-tutorial.html
Con final
palabra clave final
:
private final String name;
private final String age;
Es demasiado tarde para responder, pero puede ser útil para otros pueblos que tienen esta pregunta.
- El estado del objeto inmutable no se puede modificar después de la construcción, cualquier modificación debería dar como resultado un nuevo objeto inmutable.
- Todos los campos de la clase Inmutable deben ser finales.
- El objeto debe construirse correctamente, es decir, la referencia del objeto no debe tener fugas durante el proceso de construcción.
- El objeto debe ser final para restringir la subclase para alterar la inmutabilidad de la clase padre.
Creo que este enlace ayuda más Leer más: http://javarevisited.blogspot.com/2013/03/how-to-create-immutable-class-object-java-example-tutorial.html#ixzz40VDQDDL1
Esto está bien, pero también haría que los campos sean final
.
También haría la edad int
o double
lugar de String.
Haciendo que las variables sean privadas y sin métodos setter funcionará para tipos de datos primitivos. Si mi clase tiene una colección de objetos?
Para hacer que cualquier clase sea inmutable con un objeto de colección?
Escribe tu propio objeto de colección con la clase de colección extends y sigue las variables privadas y los métodos setter. o devolver el objeto clon de su objeto de colección.
public final class Student {
private StudentList names;//Which is extended from arraylist
public Student() {
names = DAO.getNamesList()//Which will return All Student names from Database its upto you how you want to implement.
}
public StudentList getStudentList(){
return names;//you need to implement your own methods in StudentList class to iterate your arraylist; or you can return Enumeration object.
}
public Enumeration getStudentNamesIterator(
Enumeration e = Collections.enumeration(names);
return e;
}
public class StudentList extends ArrayList {
}
Haciendo que todas las variables sean final
y al configurar un campo, haciendo que devuelva la referencia al nuevo objeto de Student
con el nuevo valor establecido como en String
.
Haga que la clase o variable sea definitiva, que sea más que suficiente
Public final class constants
{
private final String name;
private final String mobile;
// code
}
Hay pocas cosas que debes considerar para hacer una clase inmutable:
- Haz que tu clase sea
final
: ya tienes - Haga que todos los campos sean
private
yfinal
: realice los cambios apropiados en su código - No proporciones ningún método que cambie el estado de tu instancia
- Si tiene campos mutables en su clase, como
List
oDate
, hacerlosfinal
no será suficiente. Debes devolver una copia defensiva de susgetters
, para que su estado no sea mutado al llamar a los métodos.
Para el cuarto punto, digamos que tiene un campo de Date
en su clase, entonces el getter para ese campo debería verse así:
public Date getDate() {
return new Date(this.date.getTime());
}
Hacer una copia defensiva puede convertirse en un dolor de cabeza, cuando su campo mutable en sí mismo se compone de algún campo mutable, y que a su vez puede contener algún otro campo mutable. En ese caso, necesitarías hacer una copia de cada uno de forma iterativa. Nombramos esta copia iterativa de campos mutables como Deep Copy .
Implementar copias en profundidad puede ser engorroso. Pero, manteniendo ese tema aparte, debería considerar el diseño de su clase de nuevo, una vez que se ve a sí mismo cayendo en tal requisito de hacer una copia defensiva profunda.
Solo puede seguir las pautas que se muestran en este ejemplo (primer resultado en google): http://www.javapractices.com/topic/TopicAction.do?Id=29
Su ejemplo ya es un objeto inmutable, porque los campos de la clase Student solo pueden configurarse en la inicialización de la instancia.
Para hacer que el objeto sea inmutable, debe seguir estos pasos:
- No use ningún método que pueda cambiar los campos de su clase. Por ejemplo, no use Setters.
- Evite usar campos públicos no finales. Si sus campos son públicos, debe declararlos como definitivos e inicializarlos en el constructor o directamente en la línea de declaración.
Tu clase no es inmutable estrictamente hablando, solo es efectivamente inmutable. Para que sea inmutable, debes usar el final
:
private final String name;
private final String age;
Aunque la diferencia puede parecer sutil, puede marcar una diferencia significativa en un contexto de subprocesos múltiples . Una clase inmutable es intrínsecamente segura para subprocesos, una clase efectivamente inmutable es segura para subprocesos solo si se publica con seguridad.
Ya es inmutable: no puede cambiar el contenido una vez que lo inicializa, ya que no ha creado setters. Puede agregar palabras clave finales a las variables.