Vedo la maggior parte dei POJO immutabili scritti in questo modo:
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;
}
}
Eppure tendo a scriverli in questo modo:
public class MyObject {
public final String foo;
public final int bar;
public MyObject(String foo, int bar) {
this.foo = foo;
this.bar = bar;
}
}
Nota che i riferimenti sono definitivi, quindi l'oggetto è ancora immutabile. Mi permette di scrivere meno codice e consente un accesso più breve (di 5 caratteri: the get
e ()
).
L'unico svantaggio che posso vedere è se vuoi cambiare l'implementazione di getFoo()
down the road per fare qualcosa di folle, non puoi. Ma realisticamente, ciò non accade mai perché l'Oggetto è immutabile; puoi verificare durante l'istanza, creare copie difensive immutabili durante l'istanza (vedi Guava's ImmutableList
per esempio) e preparare gli oggetti foo
o bar
per la get
chiamata.
Ci sono degli svantaggi che mi mancano?
MODIFICARE
Suppongo che un altro svantaggio che mi manca siano le librerie di serializzazione che utilizzano la riflessione sui metodi che iniziano con get
o is
, ma è una pratica piuttosto terribile ...
String
, int
o MyObject
. Nella prima versione, final
è solo per garantire che metodi diversi dal costruttore all'interno della classe non provino bar = 7;
, ad esempio. Nella seconda versione, final
è necessario per evitare che i consumatori fare: MyObject x = new MyObject("hi", 5); x.bar = 7;
.
Object
è ancora immutabile " è fuorviante - in questo modo sembra che pensi che final Object
sia immutabile, cosa che non lo è. Scusa per il fraintendimento.
myObj.getFoo().setFrob(...)
.
final
non rende immutabile una variabile. Normalmente utilizzo un progetto in cui definisco ifinal
campi prima di creare la richiamata in modo che la richiamata possa accedere a quei campi. Ovviamente può chiamare tutti i metodi compreso qualsiasisetX
metodo.