Окончательный модификатор Java

Мне сказали, что я неправильно понимаю эффекты final. Каковы эффекты ключевого слова final?

Вот краткий обзор того, что я думаю, я знаю:

Модификатор Java окончательный (так называемое отношение агрегации)

примитивные переменные: можно установить только один раз. (память и производительность прибыль)
переменные объектов: могут быть изменены, окончательное относится к объекту ссылка.
поля: можно установить только один раз.
методы: нельзя переопределить, скрывать.
классы: невозможно продлить.
сбор мусора: заставит сборку мусора для генерации Java mark-sweep для двойной развертки.

Can и Cant

  • Может сделать клон неудачным (это хорошо и плохо)
  • Может создавать неизменяемые примитивы aka const
  • Может сделать пустой неизменный - инициализирован при создании aka readonly
  • Может сделать объекты неграмотными неизменными
  • Может сделать видимость видимости/видимость неизменной
  • Могут ли уменьшить накладные расходы на вызов метода (поскольку ему не нужна виртуальная таблица)
  • Может использовать аргументы метода как окончательные (даже если у вас нет)
  • Может сделать объекты потокобезопасными (если объект определен как final, он не сделает окончательные аргументы метода)
  • Можете сделать макетные тесты (не то, чтобы вы могли что-то с этим сделать), вы можете сказать, что есть ошибки)
  • Невозможно подружиться (переменимо с другими друзьями и неизменным для отдыха)
  • Невозможно сделать mutable, который будет изменен, чтобы быть неизменным позже (но может с шаблоном factory как исправление)
  • Невозможно сделать элементы массива неизменяемыми, ака глубоко неизменяемыми.
  • Невозможно создать новые экземпляры объекта (это хорошо и плохо)
  • Невозможно выполнить сериализацию.

Нет альтернатив final, но есть оболочка + private и перечисления.

Ответ 1

Отвечая на каждую из ваших точек по очереди:

примитивные переменные: могут быть установлены только один раз. (память и коэффициент усиления)

Да, но нет усиления памяти и нет увеличения производительности. (Предполагаемый прирост производительности зависит от настройки только один раз... не от final.)

переменные объектов: могут быть изменены, final применяется к объектной ссылке.

Да. (Однако это описание не соответствует тому, что это полностью согласуется с тем, как остальная часть языка Java имеет дело с двойственностью объекта/ссылки. Например, когда объекты передаются как параметры и возвращаются как результаты.)

: можно установить только один раз.

Реальный ответ: тот же, что и для переменных.

методы: не могут быть переопределены, скрыты.

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

классы: не могут быть расширены.

Да. Но также см. Примечание выше.

сбор мусора: заставит Java-генерацию мусора собирать метку для двойной развертки.

Это вздор. Ключевое слово final не имеет никакого отношения к сборке мусора. Возможно, вы сбиваете с толку final с завершением... они не связаны.

Но даже финализаторы не форсируют лишнюю развертку. Что происходит, так это то, что объект, который нуждается в завершении, устанавливается с одной стороны, пока основной GC не закончится. Затем GC запускает метод finalize для объекта и устанавливает его флаг... и продолжает. В следующий раз, когда GC запускается, объект рассматривается как обычный объект:

  • если он доступен, он помечен и скопирован
  • если он недоступен, он не помечен.

(Ваша характеристика - "Явная генерация мусора для генерации мусора Java" искажена. Сборщик мусора может быть либо "mark-sweep", либо "generational" (подкласс "копирование" ). Это не может быть и то, и другое. Java обычно использует коллекцию поколений и только возвращается к разметке в чрезвычайных ситуациях, т.е. При нехватке места или когда сборщик с низкой паузой не может идти в ногу.)

Может сделать клон неудачным (это хорошо и плохо)

Я так не думаю.

Может создавать неизменяемые примитивы aka const

Да.

Может сделать пустой неизменный - инициализирован при создании aka readonly

Да... хотя я никогда не слышал ранее употребляемого слова "пустой неизменный".

Может сделать объекты неперемещаемыми

Изменчивость объекта связана с изменением наблюдаемого состояния. Таким образом, объявление атрибутов final может или не может заставить объект вести себя как неизменяемый. Кроме того, понятие "неглубоко неизменное" не определено четко, не в последнюю очередь потому, что понятие "мелкого" не может быть отображено без глубокого знания семантики класса.

(Чтобы быть ясным, изменчивость переменных/полей является четко определенной концепцией в контексте JLS. Это просто концепция изменчивости объектов undefined с точки зрения JLS.)

Может сделать видимость видимости/видимость неизменной

Терминологическая ошибка. Мутируемость - это состояние объекта. Видимость и область видимости отсутствуют.

Может сделать служебную нагрузку вызова метода меньшей (потому что ей не нужна виртуальная таблица)

На практике это не имеет значения. Современный JIT-компилятор также делает эту оптимизацию для не конечных методов, если они не переопределены каким-либо классом, который фактически использует приложение. (Умное вещество случается...)

Можно использовать аргументы метода как окончательные (даже если у вас нет)

А? Я не могу разобрать это предложение.

Может создавать объекты threadafe

В определенных ситуациях да.

(если объект определен как final, он не будет окончательным аргументом метода)

Да, если вы имеете в виду, если класс является окончательным. Объекты не являются окончательными.

Можете сделать макетные тесты (не то, чтобы вы могли что-то с этим сделать), вы можете сказать, что предполагаются ошибки)

Не разбирается.

Невозможно подружиться (переменимо с другими друзьями и неизменным для отдыха)

В Java нет "друзей".

Невозможно сделать mutable, который будет изменен, чтобы быть неизменным позже (но может с шаблоном factory как исправление)

Да для первого поля final нельзя переключить с измененного на неизменяемое.

Неясно, что вы подразумеваете под второй частью. Верно, что вы можете использовать шаблон factory (или построитель) для создания неизменяемых объектов. Однако, если вы используете final для полей объекта ни в какой точке, объект будет изменяться.

В качестве альтернативы вы можете реализовать неизменяемые объекты, которые используют нефинализированные поля для представления неизменяемого состояния, и вы можете разработать API, чтобы вы могли "перевернуть переключатель", чтобы сделать ранее измененный объект неизменным с этого момента. Но если вы примете такой подход, вам нужно быть более осторожным с синхронизацией... если ваши объекты должны быть потокобезопасными.

Невозможно сделать элементы массива неизменными, ака глубоко неизменными

Да, но ваша терминология нарушена; см. комментарий выше о "мелкой изменчивости".

Невозможно создать новые экземпляры объекта (это хорошо и плохо)

Нет. Там ничего не мешает вам создать новый экземпляр объекта с конечными полями или окончательный класс или окончательные методы.

Невозможно выполнить сериализацию

Нет. Сериализация работает. (Конечно, десериализация полей final с использованием пользовательского метода readObject представляет проблемы... хотя вы можете обойти их с помощью рефлексивных хаков.)

Нет альтернатив окончательному,

Правильно.

но существует оболочка + private

Да, по модулю, что (строго говоря) несинхронизированный геттер для не конечного поля может быть небезопасным... даже если он инициализируется при построении объекта и никогда не менялся!

и перечисления.

Решает другую проблему. И enums может быть изменен.

Ответ 2

Конечное ключевое слово обычно используется для сохранения неизменности. Использовать final для классов или методов - это предотвращение нарушения связей между методами. Например, предположим, что реализация некоторого метода класса X предполагает, что метод M будет вести себя определенным образом. Объявление X или M как final предотвратит переопределение производных классов таким образом, чтобы заставить X вести себя некорректно.