Какая разница между экземпляром в поле и экземпляром в конструкторе?

В чем разница между этим:

public class SomeClass {
    SomeObject obj = new SomeObject();
    //rest of the code
}

и этот

public class SomeClass {
    SomeObject obj;
    public SomeClass(){
       obj = new SomeObject();
    }
    //rest of the code
}

Ответ 1

В соответствии с разделом 12.5 Создание экземпляров нового класса Спецификации языка Java:

Как раз перед ссылкой на новость созданный объект возвращается как результат, указанный конструктор обработан для инициализации нового объекта используя следующую процедуру:

  • Назначьте аргументы для конструктора вновь созданному параметру переменные для этого конструктора вызов.
  • Если этот конструктор начинается с явного вызова конструктора другой конструктор того же класса (используя это), затем оцените аргументы и процесс, которые конструктор вызов, рекурсивно использующий эти те же пять шагов. Если этот конструктор вызов завершается резко, тогда эта процедура завершается внезапно для по той же причине; в противном случае продолжить с шагом 5.
  • Этот конструктор не начинается с явного конструктора вызов другого конструктора в тот же класс (используя это). Если это конструктор для другого класса, кроме Объект, то этот конструктор будет начните с явного или неявного вызов конструктора суперкласса (используя супер). Оценить аргументы и обрабатывать этот суперкласс вызов конструктора рекурсивно используя эти пять шагов. Если это завершение конструктора завершается внезапно, тогда эта процедура завершается внезапно для того же причина. В противном случае перейдите к шагу
  • Выполнить инициализаторы экземпляра и инициализаторы переменных экземпляра для этот класс, присваивая значения инициализаторы переменных экземпляра соответствующих переменных экземпляра в порядок слева направо, в котором они текстовое отображение в исходном коде для класса. Если выполнение любого из эти инициализаторы приводят к исключение, то дальше инициализаторы обрабатываются, и это процедура завершается резко с такое же исключение. В противном случае продолжите с шагом 5. (В некоторых ранних реализации, компилятор неверно пропустил код для инициализировать поле, если поле выражение инициализатора было константой выражение, значение которого было равно значение инициализации по умолчанию для его тип.)
  • Выполните оставшуюся часть тела этого конструктора. Если это выполнение завершается резко, то это процедура завершается внезапно для та же самая причина. В противном случае эта процедура нормально завершается.

Таким образом, разница - это только шаг (шаг 4. или шаг 5), но результат тот же.

Ответ 2

Единственное различие заключается в какой шаг инициализируется ссылка. Конечный эффект тот же.

Ответ 3

Это только вопрос стиля, он компилируется в тот же код.

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

Ответ 4

В первом случае obj будет инициализирован до запуска конструктора. Это важный нюанс, когда у вас есть подклассы. Заказом конструкторов и блоков инициализации будет:

  • инициализаторы суперкласса
  • конструктор суперклассов
  • инициализаторы подкласса
  • конструктор подкласса

Ответ 5

Один аспект еще не упомянутый:

public class SomeClass {
    SomeObject obj = new SomeObject();
    //rest of the code
}

инициализирует obj фиксированному значению. Но при инициализации в конструкторе вы можете заставить инициализацию зависеть от параметров конструктора или (с несколькими конструкторами) использовать совершенно разные выражения инициализации, например.

public class SomeClass {
    private SomeObject obj;
    public SomeClass(int length){
       obj = new SomeObject(3 * length + 7);
    }
    //rest of the code
}

Ответ 6

Время построения. Первое выполняется до ввода основной. Другая конструкция объекта задерживается до вызова SomeClass ctor.