Я поражен тем, что на самом деле никто не опубликовал какой-то реальный код, который был декомпилирован, чтобы доказать, что есть хоть какая-то незначительная разница.
Для справки это было проверено на соответствие javacверсии 8, 9и10 .
Предположим, этот метод:
public static int test() {
/* final */ Object left = new Object();
Object right = new Object();
return left.hashCode() + right.hashCode();
}
Компиляция этого кода , как она есть, производит точно такой же байт - код , как когда finalбы присутствовал (final Object left = new Object(); ).
Но этот:
public static int test() {
/* final */ int left = 11;
int right = 12;
return left + right;
}
Производит:
0: bipush 11
2: istore_0
3: bipush 12
5: istore_1
6: iload_0
7: iload_1
8: iadd
9: ireturn
Уход, finalчтобы присутствовать, производит:
0: bipush 12
2: istore_1
3: bipush 11
5: iload_1
6: iadd
7: ireturn
Код в значительной степени не требует пояснений, в случае, если есть постоянная времени компиляции, он будет загружен непосредственно в стек операндов (он не будет сохранен в массив локальных переменных, как в предыдущем примере через bipush 12; istore_0; iload_0 ), что имеет смысл так как никто не может изменить это.
С другой стороны, почему во втором случае компилятор не выдает, istore_0 ... iload_0это за мной, это не похоже на этот слот0 используется каким-либо образом (он может уменьшить массив переменных таким образом, но может быть, я пропускаю некоторые внутренние детали, не могу расскажу наверняка)
Я был удивлен, увидев такую оптимизацию, учитывая, как это javacделают маленькие . Что мы должны всегда использовать final? Я даже не собираюсь писать JMHтест (который я хотел изначально), я уверен, что различия в порядке ns(если это вообще возможно). Единственное место, где это может быть проблемой, - это когда метод не может быть встроен из-за его размера (и объявленияfinal уменьшит этот размер на несколько байтов).
Есть еще два finalвопроса, которые необходимо решить. Во-первых, когда метод final(с JITточки зрения), такой метод является мономорфным - и это самые любимые изJVM .
Тогда есть finalпеременные экземпляра (которые должны быть установлены в каждом конструкторе); они важны, так как они гарантируют правильно опубликованную ссылку, о которой мы немного поговорили, а также указано именно JLS.