Почему окончательная переменная должна быть инициализирована до завершения конструктора?

Почему конечная переменная должна быть инициализирована до завершения конструктора?

public class Ex
{
  final int q;
}

Когда я компилирую этот код, я получаю ошибку, подобную этой

err: переменная q может не быть инициализирована

Ответ 1

Официальная причина заключается в том, что это определяется спецификацией языка Java 8.3.1.2:

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

Пустой final - это конечная переменная, в объявлении которой отсутствует инициализатор (то есть то, что вы описываете).

Ответ 2

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

В вашем случае он будет называться blank final, поскольку он не инициализируется при объявлении.

Ответ 3

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

Ответ 4

A final переменная должна быть инициализирована в объявлении или в конструкторе.

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

Этот фрагмент Википедии хорошо объясняет:

Конечная переменная может быть инициализирована только один раз, либо через инициализатор, либо оператор присваивания. Его не нужно инициализировать в точке объявления: это называется "пустой конечной" переменной. Чистая конечная переменная экземпляра класса должна быть обязательно назначена в конце каждого конструктора класса, в котором она объявлена; аналогично, пустая конечная статическая переменная должна быть определенно назначена в статическом инициализаторе класса, в котором она объявлена: в противном случае в обоих случаях возникает ошибка времени компиляции. (Примечание. Если переменная является ссылкой, это означает, что переменная не может быть привязана к ссылке на другой объект. Но объект, который он ссылается, по-прежнему изменен, если он был первоначально изменен.)

Ответ 5

Ключевое слово final, примененное к полю, имеет один из двух эффектов:

  • в примитиве, он предотвращает изменение значения примитива (int не может изменить значение)
  • для объекта, он предотвращает изменение "значения переменной", то есть ссылки на объект. То есть, если у вас есть final HashMap<String,String> a, вы сможете установить его только один раз, и вы не сможете сделать this.a=new HashMap<String,String>(); снова, но ничто не мешает вам делать this.a.put("a","b"), s с тех пор который не изменяет ссылку, а только содержимое объекта.

Ответ 6

Модификатор final не позволяет изменять значение переменных, поэтому вы должны инициализировать его там, где вы его объявляете.

Ответ 7

Final modifier не позволяет change your variable value. Поэтому вам нужно назначить ему значение в каком-либо месте, а constructor - это место, которое вы должны сделать в этом случае.

Ответ 8

Спецификация языка содержит конкретные гарантии о свойствах конечных переменных и полей, и один из них состоит в том, что правильно построенный объект (т.е. тот, чей конструктор успешно завершен) должен иметь все свои поля конечного экземпляра, инициализированные и видимые для всех потоков. Таким образом, компилятор анализирует пути кода и требует, чтобы вы инициализировали эти поля.

Ответ 9

Если переменная экземпляра объявлена с ключевым словом final, это означает, что она не может быть изменена позже, что делает ее константой. Вот почему мы должны инициализировать переменную с помощью конечного ключевого слова. Инициализация должна выполняться явно, поскольку JVM не предоставляет значение по умолчанию для конечной переменной экземпляра. Финальная переменная экземпляра должна быть инициализирована либо во время объявления, например:

class Test{
   final int num = 10;
   }

или он должен быть объявлен внутри блока экземпляра, например:

class Test{
 final int x;
  {
   x=10;
  }
} 

или он должен быть объявлен ДО конструктора COMPLETION, например:

class Test{
 final int x;
  Test(){ 
   x=10;
  }
}

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