Должен ли я объявить поле "final" в java, если оно не изменено в коде?

Мой вопрос в основном о производительности. Компилятор лучше знает, что, например, некоторая переменная НЕ изменяется после создания объекта. Итак, зачем беспокоиться о финале?

Я предполагаю, что многие структурные/логические причины могут прийти сюда, но с точки зрения производительности? Это имеет значение?

Спасибо,

Ответы

Ответ 1

В современной JVM финальная версия не должна влиять на производительность. Это особенно справедливо для частных полей, но даже для не-частных полей JIT может оптимизировать нефинализированные поля, поскольку они считаются окончательными, а затем deoptimize, если он загружает некоторые код, который действительно модифицирует поле.

Тем не менее, основная причина использования final - это не производительность, а сделать код более удобным. Делая финал полей, вы уменьшаете количество "движущихся частей", о которых читатели вашего кода должны думать, что значительно облегчает рассуждение о коде.

Ответ 2

Я сомневаюсь, что это будет иметь значение с точки зрения производительности, но, вероятно, это хорошая идея, если вы (но, скорее, какой-то другой новый разработчик) попытаетесь изменить это поле в коде. Если он отмечен как final, это не позволит вам его компилировать.

Ответ 3

Использование final для поля также имеет последствия для безопасности потоков. Модель памяти Java утверждает, что значения полей final становятся видимыми для всех потоков, которые могут обращаться к объекту как как только закончится конструктор этого объекта. Эта гарантия похожа на поля volatile, где любой поток всегда видит текущее значение. Для нормальных полей такой гарантии нет.

И, как отмечали другие, JIT может выполнять агрессивные оптимизации для полей final, которые не так-то просто для нормальных полей, где любой вновь загруженный класс может иметь доступ к записи в поле.

Ответ 4

final используется во время компиляции, чтобы принять или отклонить ваш исходный код как действительный. Он не должен иметь никаких последствий во время выполнения.

Ответ 5

Если поле ничего, кроме private, JVM всегда должен быть подготовлен к тому, что класс, который он еще не встретил, в какой-то момент будет загружен и начнет его изменять. Таким образом, для этих полей возможно, что явное объявление их final позволит усилить оптимизацию в JIT. Это может быть даже верно для частных полей, если JIT рассматривает один метод за раз.

С другой стороны, final для локальных переменных не выдерживает компиляцию байт-кода и поэтому не имеет эффектов производительности.

Ответ 6

Для локальных переменных окончательный модификатор не сохраняется в байте-коде, поэтому не может быть разницы в производительности. Для члена поля последствия производительности более сложны. Это может дать jit подсказку о том, что поле не изменяется и позволяет кэшировать значение в регистре. С другой стороны, final дает некоторые гарантии относительно видимости значения полей для других потоков, что может фактически замедлить конструкцию объекта.

Эффективность, я думаю, это микро-оптимизация, эффект которой вряд ли измерим.

Я бы порекомендовал использовать финал, когда это возможно, чтобы прояснить ваши намерения для ваших коллег и вашего будущего.

Ответ 7

Использование final на самом деле не является подсказкой для компилятора или JIT. Это намек на себя или других разработчиков, поддерживающих код. Это дает понять, что остальная часть кода класса предполагает, что это поле никогда не изменяется, что может быть особенно важным (например, для правильности и/или соображений безопасности потоков). Он также гарантирует, что подкласс не может изменить его значение (если поле protected).

hashCode объекта можно, например, кэшировать, если все поля, участвующие в его значении, являются окончательными.