Почему конечная переменная должна быть инициализирована до завершения конструктора?
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, потому что инициализация должна быть выполнена до завершения конструктора.