Неизменный в Яве - PullRequest
       50

Неизменный в Яве

3 голосов
/ 29 сентября 2011

В Эффективная Java , Блох рекомендует сделать все поля окончательными при создании неизменяемого объекта.

Нужно ли это делать? Не просто не дает методы доступа сделать его неизменным.

Например

class A {
      private int x;
      A (int x) {
          this.x = x;
      }
}

Приведенный выше класс является неизменным, даже если я не объявляю x как final верно? Я что-то упустил?

Ответы [ 7 ]

6 голосов
/ 29 сентября 2011

В дополнение к точке @ Божо, объявление поля как final означает, что к нему можно безопасно обращаться без какой-либо синхронизации.

Напротив, если поле не final, существует небольшой риск того, что другой поток увидит аномальное значение для поля, если оно получит к нему доступ без надлежащей синхронизации. Это может произойти, даже если ничто не изменит значения поля после создания объекта!

5 голосов
/ 29 сентября 2011

Это не «полностью» неизменяемый, потому что вы можете изменить значения.Следующим будет кто-то в команде, назначивший новое значение для поля.final указывает на намерение неизменности.

3 голосов
/ 01 октября 2011

Класс 'Effectively Immutable', как Параллелизм Java на практике определяет термин.

Это означает, что, пока ссылки на экземпляры "безопасно публикуются", они неизменны,Безопасная публикация ссылки предполагает использование синхронизации, так что модель памяти Java (JMM) может гарантировать, что вызывающие абоненты увидят значение поля полностью записанным.Например, если поле не является окончательным, а экземпляр создается и передается другому потоку, другой поток может видеть поле в неопределенном состоянии (например, null, если это ссылка на объект, или только половина из 64-bit long field).

Если экземпляр используется только в одном потоке, различие не имеет значения.Это связано с тем, что JMM использует семантику « в потоке as-if-serial ».Таким образом, присвоение поля в конструкторе всегда будет происходить до того, как поле будет прочитано.

Если поле было final, JMM гарантирует, что вызывающие абоненты увидят правильное значение, независимо от того, как ссылкабыл опубликован.Так что final имеет преимущество, если вы хотите передать экземпляр другим потокам без использования форм синхронизации.

2 голосов
/ 29 сентября 2011

Вы всегда можете установить приватное поле с помощью setAccessible.Так работают Spring, Hibernate и другие подобные фреймворки.Если также возможно создать подкласс A, то возникает вопрос о том, являются ли все экземпляры A неизменяемыми или нет.

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

(я полагаю, вы знаете о преимуществах неизменности в целом, потому что вы спросили только о механизмах.)

2 голосов
/ 29 сентября 2011

В нынешнем виде да, этот класс неизменен.Игнорирование размышлений конечно.

Однако, как говорит @Bozho, требуется только кто-то, добавляющий метод, чтобы изменить это.

Создание x финала обеспечивает дополнительную безопасность и проясняет ваши намерения.

2 голосов
/ 29 сентября 2011

Вы также можете сделать это, но компилятор поможет вам, когда вы объявите его окончательным.Как только вы попытаетесь присвоить новое значение переменной-члену, компилятор выдаст ошибку.

0 голосов
/ 29 сентября 2011

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

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