Im Gegensatz zu dem, was viele Leute glauben, ist final
es nicht erforderlich , eine unveränderliche Klasse zu bilden .
Das Standardargument für die Erstellung unveränderlicher Klassen final
lautet: Wenn Sie dies nicht tun, können Unterklassen die Veränderlichkeit erhöhen und damit den Vertrag der Oberklasse verletzen. Klienten der Klasse werden Unveränderlichkeit annehmen, werden aber überrascht sein, wenn etwas unter ihnen mutiert.
Wenn Sie dieses Argument auf das logische Extrem bringen, sollten alle Methoden ausgeführt werden final
, da andernfalls eine Unterklasse eine Methode auf eine Weise überschreiben könnte, die nicht dem Vertrag ihrer Oberklasse entspricht. Es ist interessant, dass die meisten Java-Programmierer dies als lächerlich ansehen, aber irgendwie mit der Idee einverstanden sind, dass unveränderliche Klassen sein sollten final
. Ich vermute, dass es etwas damit zu tun hat, dass Java-Programmierer im Allgemeinen nicht ganz mit dem Begriff der Unveränderlichkeit vertraut sind und vielleicht eine Art unscharfes Denken in Bezug auf die vielfältigen Bedeutungen des final
Schlüsselworts in Java.
Die Einhaltung des Vertrags Ihrer Oberklasse kann oder sollte vom Compiler nicht immer durchgesetzt werden. Der Compiler kann bestimmte Aspekte Ihres Vertrags erzwingen (z. B. einen Mindestsatz von Methoden und deren Typensignaturen), aber es gibt viele Teile typischer Verträge, die vom Compiler nicht erzwungen werden können.
Unveränderlichkeit ist Bestandteil des Vertrages einer Klasse. Es unterscheidet sich ein wenig von einigen Dingen, an die die Leute eher gewöhnt sind, weil es besagt, was die Klasse (und alle Unterklassen) nicht können, während ich denke, dass die meisten Java- (und im Allgemeinen OOP-) Programmierer dazu neigen, Verträge als verhältnismäßig zu betrachten Was eine Klasse kann , nicht was sie nicht kann .
Unveränderlichkeit betrifft auch mehr als nur eine einzelne Methode - sie betrifft die gesamte Instanz -, aber dies unterscheidet sich nicht wesentlich von der Art equals
und Weise und hashCode
in der Java-Arbeit. Für diese beiden Methoden ist ein spezifischer Vertrag festgelegt Object
. Dieser Vertrag legt sehr sorgfältig Dinge fest, die diese Methoden nicht können. Dieser Vertrag wird in Unterklassen präzisiert. Es ist sehr leicht zu überschreiben equals
oder hashCode
auf eine Weise, die gegen den Vertrag verstößt. Wenn Sie nur eine dieser beiden Methoden ohne die andere überschreiben, besteht die Möglichkeit, dass Sie gegen den Vertrag verstoßen. So soll equals
und hashCode
erklärt wurde , final
in Object
dies zu vermeiden? Ich denke, die meisten würden argumentieren, dass sie nicht sollten. Ebenso ist es nicht notwendig, unveränderliche Klassen zu erstellenfinal
.
Das heißt, die meisten Ihrer Klassen, unveränderlich oder nicht, sollten es wahrscheinlich sein final
. Siehe Effektive Java Second Edition, Punkt 17: "Entwurf und Dokument zur Vererbung oder zum Verbot".
Eine korrekte Version von Schritt 3 wäre also: "Machen Sie die Klasse endgültig oder dokumentieren Sie beim Entwerfen für Unterklassen eindeutig, dass alle Unterklassen weiterhin unveränderlich sein müssen."
java.math.BigInteger
Klasse ist Beispiel, seine Werte sind unveränderlich, aber es ist nicht endgültig.