Ich bin erstaunt, dass niemand einen echten Code gepostet hat, der dekompiliert wurde, um zu beweisen, dass es zumindest einen kleinen Unterschied gibt.
Als Referenz wurde dies gegen javacVersion getestet 8, 9und 10.
Angenommen, diese Methode:
public static int test() {
/* final */ Object left = new Object();
Object right = new Object();
return left.hashCode() + right.hashCode();
}
Wenn Sie diesen Code so kompilieren, wie er ist, wird genau derselbe Bytecode erzeugt, als wenn finaler vorhanden gewesen wäre ( final Object left = new Object();).
Aber dieser:
public static int test() {
/* final */ int left = 11;
int right = 12;
return left + right;
}
Produziert:
0: bipush 11
2: istore_0
3: bipush 12
5: istore_1
6: iload_0
7: iload_1
8: iadd
9: ireturn
Weggehen finalGegenwart erzeugt werden:
0: bipush 12
2: istore_1
3: bipush 11
5: iload_1
6: iadd
7: ireturn
Der Code ist so gut wie selbsterklärend. Wenn es eine Kompilierungszeitkonstante gibt, wird er direkt auf den Operandenstapel geladen (er wird nicht wie im vorherigen Beispiel über in einem Array mit lokalen Variablen gespeichert bipush 12; istore_0; iload_0) - was sinnvoll ist da kann es niemand ändern.
Auf der anderen Seite istore_0 ... iload_0ist es mir ein Rätsel, warum der Compiler im zweiten Fall nicht produziert . Es ist nicht so, dass dieser Slot 0in irgendeiner Weise verwendet wird (es könnte das Variablenarray auf diese Weise verkleinern, aber möglicherweise fehlen mir einige interne Details, kann nicht sicher erzählen)
Ich war überrascht, eine solche Optimierung zu sehen, wenn man bedenkt, wie wenig es javactut. Wie sollen wir immer verwenden final? Ich werde nicht einmal einen JMHTest schreiben (den ich anfangs wollte), ich bin mir sicher, dass der Unterschied in der Reihenfolge liegt ns(wenn möglich überhaupt erfasst werden). Der einzige Ort, an dem dies ein Problem sein könnte, ist, wenn eine Methode aufgrund ihrer Größe nicht inline gesetzt werden konnte (und das Deklarieren finaldiese Größe um einige Bytes verkleinern würde).
Es gibt zwei weitere final, die angegangen werden müssen. Erstens, wenn eine Methode final(aus einer JITPerspektive) ist, ist eine solche Methode monomorph - und dies sind die beliebtesten von der JVM.
Dann gibt es finalInstanzvariablen (die in jedem Konstruktor festgelegt werden müssen); Diese sind wichtig, da sie eine korrekt veröffentlichte Referenz garantieren, wie hier ein wenig berührt und auch genau von der JLS.