Ich sehe die unveränderlichsten POJOs so geschrieben:
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;
}
}
Dennoch neige ich dazu, sie so zu schreiben:
public class MyObject {
public final String foo;
public final int bar;
public MyObject(String foo, int bar) {
this.foo = foo;
this.bar = bar;
}
}
Beachten Sie, dass die Referenzen endgültig sind, sodass das Objekt noch unveränderlich ist. Dadurch kann ich weniger Code schreiben und kürzeren Zugriff (mit 5 Zeichen: get
und ()
).
Der einzige Nachteil, den ich sehen kann, ist, dass Sie die Implementierung von getFoo()
Down-the-Road ändern möchten, um etwas Verrücktes zu tun, was Sie nicht können. Realistisch gesehen geschieht dies jedoch nie, weil das Objekt unveränderlich ist. Sie können dies während der Instantiierung überprüfen, unveränderliche Verteidigungskopien während der Instantiierung erstellen (siehe ImmutableList
z. B. Guave ) und die foo
oder bar
-Objekte für den get
Anruf vorbereiten .
Gibt es irgendwelche Nachteile, die ich vermisse?
BEARBEITEN
Ich vermute, ein weiterer Nachteil, den ich vermisse, ist die Verwendung von Serialisierungsbibliotheken mit Reflektion über Methoden, die mit get
oder beginnen is
, aber das ist eine ziemlich schreckliche Praxis ...
String
, int
oder MyObject
. In der ersten Version final
soll nur sichergestellt werden, dass andere Methoden als der Konstruktor innerhalb der Klasse dies beispielsweise nicht versuchen bar = 7;
. In der zweiten Version final
ist notwendig , die Verbraucher zu verhindern , dass zu tun: MyObject x = new MyObject("hi", 5); x.bar = 7;
.
Object
ist also immer noch unveränderlich. " Ist irreführend final Object
. Entschuldigung für das Missverständnis.
myObj.getFoo().setFrob(...)
.
final
macht eine Variable nicht zum unveränderlichen Objekt. Normalerweise verwende ich ein Design, in dem ichfinal
vor dem Erstellen eines Rückrufs Felder definiere , damit der Rückruf auf diese Felder zugreifen kann. Es können natürlich alle Methoden einschließlich aller Methoden aufgerufensetX
werden.