Gibt es einen Leistungsgrund, um Methodenparameter in Java als endgültig zu deklarieren?


117

Gibt es einen Leistungsgrund, um Methodenparameter in Java als endgültig zu deklarieren?

Wie in:

public void foo(int bar) { ... }

Gegen:

public void foo(final int bar) { ... }

Angenommen, das barwird nur gelesen und nie geändert foo().


Ich kann mir keinen Grund vorstellen, warum es den Compiler interessieren würde, ob Sie einen Methodenparameter als final deklariert haben oder nicht. Die eigentliche Antwort auf diese Frage lautet jedoch: Schreiben Sie zwei Funktionen, eine mit Endparametern und eine mit regulären Parametern. Führen Sie sie jeweils millionenfach aus und prüfen Sie, ob sich die Laufzeit merklich unterscheidet. Wenn Sie sich Sorgen um die Leistung machen, ist es sehr wichtig, einige Profilierungsarbeiten an Ihrem Code durchzuführen und genau herauszufinden, was Sie verlangsamt. Es ist mit ziemlicher Sicherheit nicht das, was Sie erwarten würden :)
Mike Blandford

1
Ich würde vorschlagen, dass Sie niemals Mikro-Benchmarks schreiben. Sie wissen nicht, welche Optimierung die JIT wann durchführen kann, und Sie würden wahrscheinlich eine falsche Vorstellung davon bekommen, wie sie sich verhält, wenn Sie nur einen "einfachen Testfall" durchführen
Edmondo1984,

Nun, das mag sein, aber niemand hier hat ein Mikrobenchmark geschrieben oder vorgeschlagen ...
Kip

1
Die Antwort von @Mike Blandford schlägt vor, einen Mikro-Benchmark zu verwenden, nicht wahr?
Ben Seite

Das Schreiben von Mikro-Benchmarks in Java ist etwas sehr, sehr
Kniffliges

Antworten:


97

Das endgültige Schlüsselwort wird in der Klassendatei für lokale Variablen und Parameter nicht angezeigt und kann daher die Laufzeitleistung nicht beeinflussen. Es dient nur dazu, die Absicht des Codierers zu klären, dass die Variable nicht geändert wird (was viele als zweifelhaften Grund für ihre Verwendung betrachten) und sich mit anonymen inneren Klassen zu befassen.

Es gibt viele Argumente darüber, ob der endgültige Modifikator für die Methode selbst einen Leistungsgewinn aufweist, da die Methoden ohnehin zur Laufzeit vom optimierenden Compiler eingefügt werden, unabhängig vom Modifikator. In diesem Fall sollte es auch nur verwendet werden, um das Überschreiben der Methode einzuschränken.


5
Sie würden denken, dass endgültige Variablen / Parameter zwar als Schleifenvariablen optimiert werden könnten ... aber ein guter Compiler / eine gute Laufzeit sollte dies ohnehin ohne endgültige herausfinden können ...
John Gardner

9
Ich habe gesehen, dass der Compiler von Sun einen geringfügig kürzeren Bytecode ausgibt, wenn der einzige Unterschied zwischen den beiden Methoden die "Endgültigkeit" lokaler Variablen war. Mikrooptimierungen sind eine echte Sache, und Compiler machen sie tatsächlich. Was wirklich wichtig ist, ist natürlich, was die JIT mit dem Bytecode macht, und lokale Referenzen verlieren ihre "Endgültigkeit", wenn sie zu Bytecode kompiliert werden. Ich denke, aus diesem Grund wird so viel über endgültige lokale Variablen spekuliert: Es ist ziemlich nicht deterministisch, wie die Ergebnisse aussehen. Die Verwendung von endgültigen Einheimischen kann sich jedoch auf den Bytecode auswirken - für das, was es wert ist.
Christopher Schultz

Da es nicht deterministisch ist, gibt es auch keine Möglichkeit, sich auf die Optimierung zu verlassen. Natürlich kann sich seit der ursprünglichen Antwort im Jahr 2008 viel an den VM-Implementierungen geändert haben ;-)
Robin

15

Der einzige Vorteil eines endgültigen Parameters besteht darin, dass er in anonymen verschachtelten Klassen verwendet werden kann. Wenn ein Parameter nie geändert wird, erkennt der Compiler dies bereits als Teil seines normalen Betriebs, auch ohne den endgültigen Modifikator. Es ist ziemlich selten, dass Fehler dadurch verursacht werden, dass ein Parameter unerwartet zugewiesen wird. Wenn Ihre Methoden groß genug sind, um diese technische Ebene zu benötigen, verkleinern Sie sie. Die von Ihnen aufgerufenen Methoden können Ihre Parameter nicht ändern.


8
"Es ist ziemlich selten, dass Fehler dadurch verursacht werden, dass ein Parameter unerwartet zugewiesen wird." Es ist häufiger als Sie denken ...
RAY

2
@RAY Sie haben vielleicht Recht, tatsächlich habe ich keine Daten (über meine eigenen Erfahrungen hinaus), um diese Behauptung zu stützen.
Dobes Vandermeer

@DobesVandermeer genauer gesagt, das ist nicht wirklich ein "Vorteil für einen endgültigen Parameter ". Was Sie beschreiben, ist lediglich die erforderliche Syntax für alle lokalen Variablen (von denen ich Parameter als einbeziehe), damit sie für den lokalen Bereich der anonymen verschachtelten Klasse sichtbar werden.
Swooby

0

Compiler, die nach dem Laden der Klasse ausgeführt werden, wie z. B. JIT-Compiler, können die endgültigen Methoden nutzen. Folglich könnten als endgültig deklarierte Methoden einen gewissen Leistungsvorteil haben.

http://www.javaperformancetuning.com/tips/final.shtml

Oh und noch eine gute Ressource

http://mindprod.com/jgloss/final.html


10
Die Frage betraf die Erklärung der Parameter als endgültig, was keine Auswirkungen auf die Leistung hat.
Robin

Auf moderne JIT'S (Hotspot) hat das Finale überhaupt keinen (messbaren) Leistungseinfluss, egal ob auf Parameter oder die Klasse
angewendet

2
Die beiden Artikel, die Sie beide verknüpfen, legen nahe, dass final eher eine semantische Marke für die Entwickler ist und dass die JIT-Compiler möglicherweise final verwenden (aber wie andere betonten, benötigen sie diese Informationen nicht wirklich). Final ist also eher semantisch, was parallel zur Fähigkeit moderner C / ++ - Compiler ist, auf die Konstanz von Variablen und Methoden zu schließen, auch wenn sie nicht explizit als const markiert sind.
Ron

0

Nur noch ein Punkt, der über die Verwendung nicht endgültiger lokaler Variablen hinausgeht, die innerhalb der Methode deklariert wurden - die Instanz der inneren Klasse kann den Stapelrahmen überleben, sodass die lokale Variable möglicherweise verschwindet, während das innere Objekt noch lebt


-2

Ich gehe davon aus, dass der Compiler möglicherweise alle privaten statischen endgültigen Variablen mit einem primitiven Typ wie int entfernen und wie bei einem C ++ - Makro direkt in den Code einfügen könnte.

Ich habe jedoch keine Ahnung, ob dies in der Praxis gemacht wird, aber es könnte gemacht werden, um etwas Speicherplatz zu sparen.


Die Frage bezieht sich nicht auf private statc-Endvariablen.
Marquis von Lorne
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.