Инициализация переменных экземпляра Java с помощью метода

Я немного запутался в следующем фрагменте кода:

public class Test{

  int x = giveH();
  int h = 29;

  public int giveH(){
     return h;
  }

  public static void main(String args[])
  {
      Test t = new Test();
      System.out.print(t.x + " ");
      System.out.print(t.h);          
  }
}

Результат здесь 0 29, но я думал, что это должна быть ошибка компилятора, потому что переменная h не должна была инициализироваться, когда дело доходит до метода giveH(). Итак, компиляция проходит через линии сверху вниз? Почему это работает? Почему значение x 0, а не 29?

Ответы

Ответ 1

Значение по умолчанию int равно 0 (см. здесь). Поскольку вы инициализируете x до h, giveH возвращает значение по умолчанию для int (например, 0).

Если вы измените порядок, подобный этому

int h = 29;
int x = giveH();

вывод будет

29 29

Ответ 2

Компиляция в Java не требует метода, который должен быть объявлен до его использования. Java-учебник более подробно описывает инициализацию.

Здесь можно подумать об этом: компилятор сделает заметку для поиска метода с именем giveH где-то в области видимости, и он будет только ошибкой, если он покинет область действия и не найдет ее. Как только он попадает в декларацию giveH, нота разрешается, и все довольны.

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

Порядок объявления имеет значение в этом случае. Когда переменная x инициализируется, h имеет значение по умолчанию 0, поэтому giveH() вернет это значение по умолчанию. После этого переменной h присваивается значение 29.

Вы также можете посмотреть разделы спецификации Java Language Инициализация полей и Прямые ссылки во время инициализации поля.

Ответ 3

@Малобубола дал правильный ответ, но, поскольку вы, похоже, пока не понимаете, позвольте мне попытаться уточнить.

Когда Test создан, он запускает инициализацию переменной (x = giveH(), h = 29) один раз. Возможно, ваше недоразумение состоит в том, что переменная x всегда определяется выражениемH(), тогда как она определяет ее только при инициализации x.

Вот почему порядок высказываний здесь имеет решающее значение; x инициализируется до h, поэтому h равно 0, когда charH() вызывается при инициализации x.

Ответ 4

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

import java.util.ArrayList;

public class Test {
    int x = giveH();
    final int h=29;

    final public int giveH(){
        return h;
    }

    public static void main(String args[]) {
        Test t = new Test();
        System.out.print(t.x + " ");
        System.out.print(t.h);          
    }
}

Ответ 5

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