2010-11-12 3 views
53

Welchen Unterschied das Finale macht zwischen dem Code unten. Hat es einen Vorteil, die Argumente als endgültig zu deklarieren?Making Java-Methode Argumente als endgültig

public String changeTimezone(Timestamp stamp, Timezone fTz, Timezone toTz){ 
    return .... 
} 

public String changeTimezone(final Timestamp stamp, final Timezone fTz, 
     final Timezone toTz){ 
    return .... 
} 
+3

Es gibt Codeanalysatoren, die warnen, wenn ein Parameter wiederverwendet oder neu zugewiesen. (Gleiches gilt für lokale Variablen) IMHO, Dies ist ein besserer Weg, solche Parameter abzufangen, wenn Sie feststellen, dass das Ändern unerwünscht ist. –

+0

Mögliche Duplikat [Warum sollte ich das Stichwort „final“ auf Methodenparameter in Java?] (Https://stackoverflow.com/questions/500508/why-should-i-use-the-keyword-final-on -a-method-parameter-in-java) –

Antwort

75

Da ein formaler Methodenparameter eine lokale Variable ist, können Sie nur von inneren anonymen Klassen auf sie zugreifen, wenn sie als final deklariert sind.

Dies erspart Ihnen eine andere lokale letzte Variable in der Methode Körper erklärt:

void m(final int param) { 
     new Thread(new Runnable() { 
      public void run() { 
       System.err.println(param); 
      } 
     }).start(); 
    } 
+18

+1: Dies ist ein wichtiger Anwendungsfall, und das einzige Mal, wenn Sie es * brauchen *. (Der Rest der Zeit ist nur eine Frage dessen, was dem Programmierer hilft.) –

+3

Darf ich die Gründe dafür fragen? – KodeWarrior

+11

nicht mehr notwendig mit Java 8. –

10

Es macht keinen großen Unterschied. Es bedeutet nur, dass Sie nicht schreiben können:

stamp = null; 
fTz = new ...; 

aber man kann immer noch schreiben:

stamp.setXXX(...); 
fTz.setXXX(...); 

Es ist vor allem ein Hinweis auf die Wartung Programmierer, die Sie folgt, dass Sie kein zuweisen wollen neuer Wert für den Parameter irgendwo in der Mitte der Methode, wo er nicht offensichtlich ist und daher zu Verwirrung führen kann.

15

Das Finale verhindert, dass Sie der Variablen einen neuen Wert zuweisen, und dies kann hilfreich sein, um Tippfehler zu erkennen. Stilistisch möchten Sie vielleicht die erhaltenen Parameter unverändert lassen und nur lokalen Variablen zuweisen, so dass final helfen würde, diesen Stil zu erzwingen.

Muss zugeben, dass ich selten daran denke, final für Parameter zu verwenden, vielleicht sollte ich.

public int example(final int basicRate){ 
    int discountRate; 

    discountRate = basicRate - 10; 
    // ... lots of code here 
    if (isGoldCustomer) { 
     basicRate--; // typo, we intended to say discountRate--, final catches this 
    } 
    // ... more code here 

    return discountRate; 
} 
0

Es ist nur ein Konstrukt in Java, um Ihnen zu helfen, einen Vertrag zu definieren und dabei zu bleiben. Ahnliche Diskussion hier: http://c2.com/cgi/wiki?JavaFinalConsideredEvil

BTW - (wie der twiki sagt), Args als final zu markieren ist in der Regel redundant, wenn Sie gute Programmiergrundsätze folgen und die eingehende Argumentreferenz neu zuweisen/neu definieren.

Im schlimmsten Fall, wenn Sie die args-Referenz neu definieren, wirkt sich dies nicht auf den tatsächlichen Wert aus, der an die Funktion übergeben wird - da nur eine Referenz übergeben wurde.

2

Der letzte Schlüsselwort, wenn für Parameter/Variablen in Java markiert die Referenz als endgültig. Wenn ein Objekt an eine andere Methode übergeben wird, erstellt das System eine Kopie der Referenzvariablen und übergibt sie an die Methode. Indem Sie die neuen Referenzen final markieren, schützen Sie sie vor einer Neuzuweisung. Es wird manchmal eine gute Programmierpraxis betrachtet.

+1

Ich habe etwas hinzufügen: Wenn Parameter sind primitiv, ich sehe keine Unterschiede. Wenn Parameter Collections sind (eine Liste von Objekten ...), kann das Hinzufügen von final nicht verhindern, dass sie modifiziert werden. – Sam003

+1

Unveränderlichkeit ist immer ein wünschenswertes Merkmal. Java hat es nicht out of the box. Wenn die Variablen mindestens endgültig sind, wird die Integrität der Referenz sichergestellt. – Sid

+0

Ich stimme zu. Aber wenn wir wirklich Unbeweglichkeit für Objekte erreichen wollen, könnten wir versuchen, einen tiefen Klon zu erstellen. – Sam003

19

Auszug aus The final word on the final keyword

Schluss Parameter

Das folgende Beispiel erklärt endgültigen Parameter:

public void doSomething(final int i, final int j) 
{ 
    // cannot change the value of i or j here... 
    // any change would be visible only inside the method... 
} 

final hier verwendet wird, um die zwei Indizes, um sicherzustellen, i und j gewann t versehentlich durch die Methode zurückgesetzt werden. Es ist ein praktischer Weg zum Schutz vor einem heimtückischen Bug , der fälschlicherweise den Wert von Ihre Parameter ändert.Im Allgemeinen kurze Methoden sind ein besserer Weg, vor dieser Klasse von Fehlern zu schützen, aber letzte Parameter können eine nützliche Ergänzung zu Ihrem Programmierstil sein.

Hinweis, dass die endgültigen Parameter sind nicht als Teil der Verfahren Signatur und werden von den Compiler ignoriert, wenn Methodenaufrufe zu lösen. Parameter können als final deklariert werden (oder nicht), ohne Einfluss darauf, wie die -Methode überschrieben wird.

+8

Es könnte besser sein, für dieses Beispiel Objekte als Primitive zu verwenden, da primitive Änderungen immer nur innerhalb der Methode sichtbar sind. Und bei Objekten können Sie diese immer noch ändern. Sie können einfach nicht auf ein neues Objekt zeigen. In der Tat jetzt denke ich darüber nach, letzte wirklich nichts im Vergleich zu ändern, es zu Weglassen, andere als eine Variablendeklaration mit AICs speichern und mit dem Compiler Punkt aus versehentlichen Änderungen von Parametern, die Sie aus irgendeinem Grunde nicht ändern wollten . –

1

Für den Körper dieser Methode das final Schlüsselwort die Argument Referenzen wird verhindert, dass versehentlich einen Compiler-Fehler geben auf diesen Fällen (die meisten IDEs wird sich beschweren, sofort) neu zugewiesen werden. Einige mögen argumentieren, dass die Verwendung von final im Allgemeinen, wann immer es möglich ist, die Dinge beschleunigen wird, aber das ist in den letzten JVMs nicht der Fall.

0

Ich spreche von Markierung Variablen und Felder endgültig im Allgemeinen - gilt nicht nur für Argumente der Methode. (Markierungsmethoden/Klassen Finale ist eine ganz andere Sache).

Es ist ein Gefallen für die Leser/zukünftige Betreuer Ihres Codes. Zusammen mit einem sinnvollen Namen der Variablen ist es für den Leser Ihres Codes hilfreich und beruhigend zu sehen, was die betreffenden Variablen darstellen - und es ist beruhigend für den Leser, dass, wenn Sie die Variable im selben Umfang sehen, die Bedeutung erhalten bleibt das selbe, so muss er nicht seinen Kopf kratzen, um immer herauszufinden, was eine Variable in jedem Zusammenhang bedeutet. Wir haben zu viele Verstöße gegen die "Wiederverwendung" von Variablen gesehen, die sogar ein kurzes Code-Snippet schwer verständlich machen.

-3

Das Schlüsselwort final verhindert, dass Sie dem Parameter einen neuen Wert zuweisen. Ich möchte dies mit einem einfachen Beispiel

Angenommen wir ein Verfahren

method1() {

Datum dateOfBirth = new Date ("1/1/2009") haben erklären;

methode2 (dateOfBirth);

method3 (dateOfBirth); }

öffentliche mehod2 (Datum dateOfBirth) {
....
....
....
}

öffentliche mehod2 (Datum dateOfBirth) {
....
....
....
}

Wenn im oben genannten Fall "dateOfBirth" in method2 einen neuen Wert zugewiesen wird, würde dies zu einer falschen Ausgabe von method3 führen. Der Wert, der an Methode 3 übergeben wird, ist nicht der Wert, der an Methode2 übergeben wurde. Um dieses letzte Schlüsselwort zu vermeiden, wird es für Parameter verwendet.

Und dies ist auch eine der Java Coding Best Practices.

+5

Das ist nicht ganz richtig. Selbst wenn das Argument dateOfBirth in method2() in einen anderen Wert geändert wird, hat dies keine Auswirkungen auf method2(), da Java nach Wert und nicht nach Referenz übergeben wird. – Flo