Почему конечная переменная экземпляра требует инициализации, а конечная локальная переменная - нет?

Следующий пример класса не компилируется:

class Test {
    final int x;  // Compilation error: requires initialization.
}

Сообщение об ошибке компиляции для этого кода:

..\src\pkgs\main\Test.java:3: error: variable x might not have been initialized
class Test {
^

Однако Java не генерирует никаких сообщений об ошибках для класса, содержащего следующий метод:

class Test {
    void method() {
        final int x;  // Compiles OK; has no initialization.
    }
}

Что касается инициализации и ее требований, почему Java по-разному обрабатывает переменные конечного экземпляра и конечные локальные переменные? Спасибо.


person user2911290    schedule 04.05.2014    source источник
comment
Почему - довольно сложно понять. Один из возможных аргументов: конечная переменная должна быть инициализирована перед использованием - если она не используется, ее не нужно инициализировать. Последнее поле должно быть инициализировано в конце конструктора - в этот момент объект и все его поля доступны для использования кем угодно, и компилятору не нужно быть героическим, чтобы решить, может ли он когда-либо быть доступен или не будет. .   -  person Alan Stokes    schedule 04.05.2014


Ответы (3)


Любое использование, т. Е. Чтение второго случая , даст вам error. Но неиспользуемые переменные считаются предупреждением, а не ошибкой; смысл выполняемого кода однозначен, хотя, скорее всего, неверен.

В случае с конструктором компилятор не выполняет такой анализ неиспользуемых переменных, хотя бы потому, что (для чего-либо, кроме закрытых полей) он может быть прочитан в другом файле, к которому компилятор не имеет доступа.

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

person soru    schedule 04.05.2014

Переменная экземпляра неявно используется экземпляром. В приведенном вами примере локальной переменной не используется локальная переменная, поэтому ошибки нет (переменная не используется).

Ваш пример локальной переменной не будет скомпилирован (с той же ошибкой), если вы попытаетесь использовать x:

class Test {

    Test() {
        final int x;
        System.out.println(x); // <== Compilation error - "variable x might not have been initialized"
    }
}

Точно так же ваш первый пример хорош, если вы инициализируете переменную в какой-то момент, не обязательно в объявлении:

class Test {
    final int x;

    Test() {
        this.x = 10;
    }
}
person T.J. Crowder    schedule 04.05.2014
comment
@AlanStokes: Я понял, что не обращался к другой половине. Надеюсь, теперь это так. - person T.J. Crowder; 04.05.2014

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

person javadev    schedule 04.05.2014