Я поражен тем, что на самом деле никто не опубликовал какой-то реальный код, который был декомпилирован, чтобы доказать, что есть хоть какая-то незначительная разница.
Для справки это было проверено на соответствие 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
.