Ich betrachte final
in Methodenparametern und lokalen Variablen Code-Rauschen. Java-Methodendeklarationen können (insbesondere bei Generika) sehr lang sein - sie müssen nicht mehr erstellt werden.
Wenn Unit - Tests richtig geschrieben werden, um Parameter zuweisen , die „schädlichen“ werden bei Ihnen abgeholt ist, so sollte es nie wirklich ein Problem sein. Die visuelle Klarheit ist wichtiger als die Vermeidung eines möglichen Fehlers, der nicht erkannt wird, da Ihre Komponententests eine unzureichende Abdeckung aufweisen.
Tools wie FindBugs und CheckStyle, die so konfiguriert werden können, dass sie den Build unterbrechen, wenn Parameter oder lokale Variablen zugewiesen werden, wenn Sie sich intensiv mit solchen Dingen befassen.
Natürlich, wenn Sie benötigen sie endgültig zum Beispiel zu machen , weil Sie den Wert in einer anonymen Klasse verwenden, dann kein Problem - das ist die einfachste sauberste Lösung.
Abgesehen von dem offensichtlichen Effekt, zusätzliche Schlüsselwörter zu Ihren Parametern hinzuzufügen und diese dadurch zu tarnen, kann das Hinzufügen von final zu Methodenparametern häufig dazu führen, dass der Code im Methodenkörper weniger lesbar wird, was den Code verschlimmert - um "guter" Code zu sein muss so lesbar und einfach wie möglich sein. Nehmen wir als Beispiel an, ich hätte eine Methode, bei der die Groß- und Kleinschreibung nicht berücksichtigt werden muss.
Ohne final
:
public void doSomething(String input) {
input = input.toLowerCase();
// do a few things with input
}
Einfach. Reinigen. Jeder weiß, was los ist.
Jetzt mit 'final', Option 1:
public void doSomething(final String input) {
final String lowercaseInput = input.toLowerCase();
// do a few things with lowercaseInput
}
Während das final
Hinzufügen von Code durch die Parameter verhindert wird, dass der Codierer glaubt, er arbeite mit dem ursprünglichen Wert, besteht das gleiche Risiko, dass Code, der weiter unten liegt, input
anstelle dessen verwendet wird lowercaseInput
, was er nicht sollte und gegen das er nicht geschützt werden kann, weil Sie dies können. ' t take it out of scope (oder auch zuweisen null
, input
wenn das überhaupt helfen würde).
Mit 'final', Option 2:
public void doSomething(final String input) {
// do a few things with input.toLowerCase()
}
Jetzt haben wir nur noch mehr Code-Rauschen erzeugt und den Performance-Hit eingeführt, toLowerCase()
n-mal aufgerufen zu werden .
Mit 'final', Option 3:
public void doSomething(final String input) {
doSomethingPrivate(input.toLowerCase());
}
/** @throws IllegalArgumentException if input not all lower case */
private void doSomethingPrivate(final String input) {
if (!input.equals(input.toLowerCase())) {
throw new IllegalArgumentException("input not lowercase");
}
// do a few things with input
}
Sprechen Sie über Code-Rauschen. Dies ist ein Zugunglück. Wir haben eine neue Methode, einen erforderlichen Ausnahmeblock, da anderer Code ihn möglicherweise falsch aufruft. Weitere Unit-Tests, um die Ausnahme abzudecken. Alles, um eine einfache und meiner Meinung nach vorzuziehende und harmlose Linie zu vermeiden.
Es gibt auch das Problem, dass Methoden nicht so lang sein sollten, dass Sie sie nicht einfach visuell erfassen können und auf einen Blick wissen, dass eine Zuweisung zu Parametern stattgefunden hat.
Ich halte es für eine gute Praxis / einen guten Stil, wenn Sie einem Parameter einen Wert zuweisen, den Sie zu Beginn der Methode ausführen, vorzugsweise in der ersten Zeile oder direkt nach der Überprüfung der grundlegenden Eingaben, wodurch die gesamte Methode ersetzt wird Methode. Die Leser wissen, dass jede Zuordnung offensichtlich (in der Nähe der Signaturdeklaration) und an einer konsistenten Stelle erfolgen muss, wodurch das Problem, das durch das Hinzufügen von final vermieden werden soll, erheblich verringert wird. Eigentlich ordne ich selten Parameter zu, aber wenn ich das tue, tue ich es immer am Anfang einer Methode.
Beachten Sie auch, dass Sie final
nicht wirklich so geschützt sind, wie es auf den ersten Blick scheint:
public void foo(final Date date) {
date.setTime(0);
// code that uses date
}
final
Schützt Sie nur dann vollständig, wenn der Parametertyp primitiv oder unveränderlich ist.