Финальный модификатор Java - PullRequest
       3

Финальный модификатор Java

52 голосов
/ 25 октября 2010

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

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

Финальный модификатор Java (он же отношение агрегации)

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

Может и Кант

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

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

Ответы [ 2 ]

72 голосов
/ 25 октября 2010

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

Примитивные переменные: может быть установлен только один раз.(увеличение памяти и производительности)

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

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

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

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

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

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

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

классы: canне будет продлен.

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

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

Это чепуха.Ключевое слово final не имеет отношения 1042 * к сборке мусора.Возможно, вы путаете final с финализацией ... они не связаны.

Но даже финализаторы не вызывают дополнительную проверку.То, что происходит, - то, что объект, который нуждается в финализации, установлен на одной стороне, пока основной GC не заканчивает.Затем GC запускает метод finalize для объекта и устанавливает его флаг ... и продолжает.При следующем запуске GC объект обрабатывается как обычный объект:

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

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

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

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

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

Да.

Может сделать заготовку неизменной - инициализируется при создании или только для чтения

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

Может делать объекты неизменными

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

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

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

Ошибка терминологии.Изменчивость связана с состоянием объекта.Видимость и область действия не являются.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Сериализация не работает

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

Альтернативы финалу нет,

Correct.

но есть обертка + приват

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

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

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

2 голосов
/ 28 июля 2015

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...