Использование неинициализированного конечного поля-с / без 'этого.' спецификатор
может кто-нибудь объяснить мне, почему первый из двух образцов компилирует, а второй нет? Обратите внимание, что единственное различие заключается в том, что первый явно квалифицирует ссылку на x с '.этот, а не второй. В обоих случаях, окончательное поле X явно пытался быть использованы до инициализации.
Я бы подумал, что оба образца будут обрабатываться полностью одинаково, что приведет к ошибке компиляции для оба.
1)
public class Foo {
private final int x;
private Foo() {
int y = 2 * this.x;
x = 5;
}
}
2)
public class Foo {
private final int x;
private Foo() {
int y = 2 * x;
x = 5;
}
}
4 ответа:
после того, как куча spec-чтения и мысли, я пришел к выводу, что:
в компиляторе Java 5 или Java 6 это правильное поведение. Глава 16 "определенное задание Спецификация Языка Java, Третье Издание говорит:
каждая локальная переменная (§14.4) и каждый пробел
final
(§4.12.4) поле (§8.3.1.2) должен быть наверняка назначена значение когда происходит какой-либо доступ к его значению. Доступ к его значению состоит из простое имя переменной встречается в любом месте выражения, за исключением левого операнда простого оператора присваивания=
.(выделено мной). Так что в выражении
2 * this.x
наthis.x
часть не считается "доступа [x
's] значение" (и поэтому не подчиняется правилам определенного присвоения), потому чтоthis.x
- это не простое имя переменной экземпляраx
. (N. B. правило для случаев, когда происходит определенное назначение, в абзаце после приведенного выше текста,тут разрешить что-то вродеthis.x = 3
, и считаетx
чтобы быть определенно назначен после этого; это только правило для доступа, который не считаетсяthis.x
.) Обратите внимание, что значениеthis.x
в этом случае будет ноль, за §17.5.2.в компиляторе Java 7 это ошибка компилятора, но понятная один. Глава 16 "определенное назначение"Спецификация Языка Java, Java 7 SE Edition говорит:
каждая локальная переменная (§14.4) и каждый пробел
при использовании
this
в конструкторе, компилятор видитx
как атрибут членомthis
объект (по умолчанию инициализирован). Так какx
иint
, это по умолчанию инициализируется с0
. Это делает компилятор счастливым и его работа хорошо во время выполнения тоже.когда вы не используете
this
, то компилятор используетx
объявление непосредственно в лексическом анализе и, следовательно, он жалуется на его инициализацию (явление времени компиляции).так это определение
this
, Что делает компилятор для анализаx
как переменная-член объекта по сравнению с прямым атрибутом во время лексического анализа в компиляции и приводит к различному поведению компиляции.при использовании в качестве основного выражения ключевое слово this обозначает значение, которое является ссылкой на объект, для которого был вызван метод экземпляра (§15.12), или на объект строится.
Я думаю, что компилятор оценивает, что писать это.x подразумевает, что " это " существует, поэтому был вызван конструктор (и конечная переменная была инициализирована). Но вы должны получить RuntimeException при попытке запустить его
Я предполагаю, что вы имеете в виду поведение в Eclipse. (Как указано в комментарии компиляция с javac работает).
Я думаю, что это проблема затмения. Он имеет свой собственный компилятор, и собственный набор правил. Один из них заключается в том, что вы не можете получить доступ к полю, которое не инициализировано, хотя Java-commpiler инициализирует переменные для вас.