Почему конечная переменная должна быть инициализирована до завершения конструктора?
public class Ex
{
  final int q;
}
Когда я компилирую этот код, я получаю ошибку, подобную этой
err: переменная q может не быть инициализирована
Почему конечная переменная должна быть инициализирована до завершения конструктора?
public class Ex
{
  final int q;
}
Когда я компилирую этот код, я получаю ошибку, подобную этой
err: переменная q может не быть инициализирована
Официальная причина заключается в том, что это определяется спецификацией языка Java 8.3.1.2:
Пустая конечная переменная экземпляра должна быть обязательно назначена в конце каждого конструктора класса, в котором она объявлена; в противном случае возникает ошибка времени компиляции.
Пустой final - это конечная переменная, в объявлении которой отсутствует инициализатор (то есть то, что вы описываете).
Поскольку final не позволяет вам изменять переменные, но в какой-то момент он должен быть инициализирован, а конструкторы - это подходящее место.
В вашем случае он будет называться blank final, поскольку он не инициализируется при объявлении.
Значение переменной final можно установить только один раз. Конструктор - это единственное место в коде для класса, которое вы можете гарантировать, что это будет верно; конструктор только когда-либо вызывается один раз для объекта, но другие методы могут быть вызваны сколько угодно раз.
A final переменная должна быть инициализирована в объявлении или в конструкторе.
Если он не был инициализирован при возврате конструктора, он никогда не может быть инициализирован и может оставаться неинициализированной переменной. Компилятор не может доказать, что он будет инициализирован и, таким образом, выдает ошибку.
Этот фрагмент Википедии хорошо объясняет:
Конечная переменная может быть инициализирована только один раз, либо через инициализатор, либо оператор присваивания. Его не нужно инициализировать в точке объявления: это называется "пустой конечной" переменной. Чистая конечная переменная экземпляра класса должна быть обязательно назначена в конце каждого конструктора класса, в котором она объявлена; аналогично, пустая конечная статическая переменная должна быть определенно назначена в статическом инициализаторе класса, в котором она объявлена: в противном случае в обоих случаях возникает ошибка времени компиляции. (Примечание. Если переменная является ссылкой, это означает, что переменная не может быть привязана к ссылке на другой объект. Но объект, который он ссылается, по-прежнему изменен, если он был первоначально изменен.)
Ключевое слово final, примененное к полю, имеет один из двух эффектов:
final HashMap<String,String> a, вы сможете установить его только один раз, и вы не сможете сделать this.a=new HashMap<String,String>(); снова, но ничто не мешает вам делать this.a.put("a","b"), s с тех пор который не изменяет ссылку, а только содержимое объекта.Модификатор final не позволяет изменять значение переменных, поэтому вы должны инициализировать его там, где вы его объявляете.
 Final modifier не позволяет change your variable value. Поэтому вам нужно назначить ему значение в каком-либо месте, а constructor - это место, которое вы должны сделать в этом случае.
Спецификация языка содержит конкретные гарантии о свойствах конечных переменных и полей, и один из них состоит в том, что правильно построенный объект (т.е. тот, чей конструктор успешно завершен) должен иметь все свои поля конечного экземпляра, инициализированные и видимые для всех потоков. Таким образом, компилятор анализирует пути кода и требует, чтобы вы инициализировали эти поля.
Если переменная экземпляра объявлена с ключевым словом 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, потому что инициализация должна быть выполнена до завершения конструктора.