Использование неинициализированного конечного поля-с / без 'этого.' спецификатор
может кто-нибудь объяснить мне, почему первый из двух образцов компилирует, а второй нет? Обратите внимание, что единственное различие заключается в том, что первый явно квалифицирует ссылку на 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 инициализирует переменные для вас.