Мне трудно понять, как переменная экземпляра инициализируется, когда мы объявляем это. Рассмотрим следующий фрагмент:

class Rat {
    private int val = 20;
}

class Cat {
    private Rat rat = new Rat();
}

Я не могу понять, как мы инициализируем переменные экземпляра во время их объявления в классе; Разве эти переменные не должны получать свои «значения» или «ссылки», когда мы фактически создаем объект, например, в main мы делаем:

main() {

    Cat cat = new Cat();
}

Так что каждый объект имеет свой «собственный» набор переменных экземпляра; и, например, чтобы инициализировать переменную экземпляра Rat в Cat, мы должны сделать:

 cat.Rat = new Rat();

Может ли кто-нибудь помочь мне понять это.

0
CuriousMind 22 Фев 2018 в 12:20

4 ответа

Лучший ответ

Я не могу понять, как мы инициализируем переменные экземпляра во время их объявления в классе

Переменные экземпляра инициализируются при создании экземпляра. Каждый раз, когда вы создаете экземпляр Cat, выполняется private Rat rat = new Rat();. Каждый раз, когда вы создаете экземпляр Rat, выполняется private int val = 20; (сразу после выполнения конструктора суперкласса и перед выполнением тела конструктора текущего класса).

Когда

Cat cat = new Cat();

Выполняется непосредственно перед выполнением тела конструктора Cat, переменные экземпляра Cat инициализируются, поэтому

private Rat rat = new Rat();

Выполнен. Теперь, непосредственно перед выполнением тела конструктора Rat, переменные экземпляра Rat инициализируются, поэтому

private int val = 20;

Выполнен.

2
Eran 22 Фев 2018 в 09:24
class Rat {
    private int val = 20;
}

Пока вы не создадите экземпляр Rat, переменная val не будет содержать значение '20'. Итак, чтобы JVM присвоил значение 20 для val, вам нужно создать экземпляр Rat с оператором 'new'.

Similarly,
class Cat {
    private Rat rat = new Rat();
}

Если вы не создадите экземпляр Cat с помощью оператора 'new', переменная rat не будет инициализирована с экземпляром 'new Rat ()'.

Аналогично для экземпляра Cat и инициализации

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

Пожалуйста, прочитайте о сфере, чтобы узнать больше об этом.

0
student23 22 Фев 2018 в 10:21

Из приведенного ниже фрагмента кода:

main() {

    Cat cat = new Cat();
}

Очевидно, что мы пытаемся создать объект «Кошка». Поэтому, когда мы вызываем это, класс Cat будет загружен (если он еще не загружен). Пока класс загружается, он инициализирует переменные экземпляра.

В приведенном ниже сценарии

   class Cat {
    private Rat rat = new Rat();
}

Так как класс Cat имеет переменную экземпляра, которая зависит от другого класса, называемого Rat, класс Rat будет загружен, и в ходе процесса переменная экземпляра в Rat будет инициализирована.

class Rat {
    private int val = 20;
} 

Таким образом, приведенный выше фрагмент кода будет сначала инициализирован, затем будет выполнено это назначение private Rat rat = new Rat();, и, наконец, объект Cat (Cat cat = new Cat();) будет создан и назначен ему в ссылочную переменную cat.

1
Jayanth 22 Фев 2018 в 09:34

Согласно определению в https: // docs.oracle.com/javase/specs/jls/se8/html/jls-12.html#jls-12.5 полей JVM инициализируются на шаге 4 создания нового экземпляра класса. Так что прежде чем тело вашего конструктора будет выполнено.

  1. Назначьте аргументы конструктора для вновь созданных переменных параметров для этого вызова конструктора.

  2. Если этот конструктор начинается с явного вызова конструктора (§8.8.7.1) другого конструктора в том же классе (используя this), то  оценивать аргументы и обрабатывать этот вызов конструктора  рекурсивно используя те же пять шагов. Если этот конструктор  вызов завершается внезапно, затем эта процедура завершается внезапно  по той же причине; в противном случае перейдите к шагу 5.

  3. Этот конструктор не начинается с явного вызова конструктора другого конструктора в том же классе (используя это). Если  этот конструктор для класса, отличного от Object, то этот  Конструктор начнется с явного или неявного вызова  конструктор суперкласса (используя супер). Оцените аргументы и  обработать этот вызов конструктора суперкласса рекурсивно, используя эти  те же пять шагов. Если этот вызов конструктора завершается внезапно,  затем эта процедура завершается внезапно по той же причине. В противном случае,  перейдите к шагу 4.

  4. Выполните инициализаторы экземпляра и инициализаторы переменной экземпляра для этого класса, назначив значения переменной экземпляра  инициализаторы для соответствующих переменных экземпляра, в  порядок слева направо, в котором они появляются текстово в исходном коде  для класса. Если выполнение любого из этих инициализаторов приводит к  исключение, то дальнейшие инициализаторы не обрабатываются, и это  процедура завершается внезапно с тем же исключением. В противном случае,  перейдите к шагу 5.

  5. Выполните остальную часть тела этого конструктора. Если это выполнение завершается внезапно, то эта процедура завершается преждевременно для  той же причине. В противном случае эта процедура завершается нормально.

1
Ben 22 Фев 2018 в 09:26