Veo los POJO más inmutables escritos así:
public class MyObject {
private final String foo;
private final int bar;
public MyObject(String foo, int bar) {
this.foo = foo;
this.bar = bar;
}
public String getFoo() {
return foo;
}
public int getBar() {
return bar;
}
}
Sin embargo, tiendo a escribirlos así:
public class MyObject {
public final String foo;
public final int bar;
public MyObject(String foo, int bar) {
this.foo = foo;
this.bar = bar;
}
}
Tenga en cuenta que las referencias son finales, por lo que el objeto sigue siendo inmutable. Me permite escribir menos código y permite un acceso más corto (por 5 caracteres: el get
y ()
).
La única desventaja que puedo ver es que si quieres cambiar la implementación getFoo()
en el futuro para hacer algo loco, no puedes. Pero de manera realista, esto nunca sucede porque el Objeto es inmutable; puede verificar durante la creación de instancias, crear copias defensivas inmutables durante la creación de instancias (consulte Guava's, ImmutableList
por ejemplo) y preparar los objetos foo
u bar
para la get
llamada.
¿Hay alguna desventaja que me falta?
EDITAR
Supongo que otra desventaja que me falta son las bibliotecas de serialización que utilizan la reflexión sobre los métodos que comienzan con get
o is
, pero esa es una práctica bastante terrible ...
fuente
final
no hace que una variable sea el objeto inmutable. Normalmente uso un diseño donde definofinal
campos antes de crear la devolución de llamada para que la devolución de llamada pueda acceder a esos campos. Por supuesto, puede llamar a todos los métodos, incluidos lossetX
métodos.String
,int
oMyObject
. En la primera versión,final
es solo para garantizar que otros métodos que no sean el constructor dentro de la clase no intentenbar = 7;
, por ejemplo. En la segunda versión,final
es necesario evitar que los consumidores haciendo:MyObject x = new MyObject("hi", 5); x.bar = 7;
.Object
sigue siendo inmutable " es engañoso, de esa manera parece que cree que cualquierafinal Object
es inmutable, lo que no lo es. Perdón por el malentendido.myObj.getFoo().setFrob(...)
.Respuestas:
Cuatro desventajas en las que puedo pensar:
Dicho esto, tu versión es definitivamente más concisa. Si se tratara de una clase especializada que solo se utiliza dentro de un paquete específico (tal vez el alcance del paquete es una buena idea aquí), entonces podría considerar esto para casos únicos. Pero no expondría las principales API como esta.
fuente
Deshazte de los captadores / setters también, ¡y estás bien!
Este es un tema muy controvertido entre los programadores de Java.
De todos modos, hay dos situaciones en las que uso variables públicas en lugar de (get) / setters:
fuente
En palabras simples:
fuente
Una posible desventaja que puedo ver de improviso es que está vinculado a la representación interna de los datos en la clase. Probablemente esto no sea un gran problema, pero si usa los setters, y decide que foo y bar serán devueltos de alguna otra clase definida en otro lugar, las clases que consumen MyObject no deberían cambiar. Solo necesitaría tocar MyObject. Sin embargo, si usa los valores desnudos, entonces tendría que tocar en todas partes el MyObject que usé.
fuente