Инициализация нестатической переменной-члена Java

Вероятно, это «дубликат», но я не знаю, как искать этот вопрос...

Я инициализирую нестатическую переменную-член в строке объявления:

public class A
{
    private B b = new B();
    ...
}

Я делаю это вместо того, чтобы инициализировать эту переменную внутри конструктора по умолчанию:

public class A
{
    private B b;
    public A()
    {
        b = new B();
    }
    ...
}

Есть ли какая-либо разница между ними, за исключением (возможно) того, что первый не является «ANSI Java» или что-то в этом роде?

Я получаю два разных байт-кода (т. е. два разных файла «класса») для двух приведенных выше реализаций, что наводит меня на мысль, что могут быть различия во время выполнения.

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

Спасибо


person barak manos    schedule 12.01.2014    source источник


Ответы (5)


Первый — это объявление и инициализация одновременно.

Вместо этого во втором примере у вас есть объявление переменной b, которое не инициализировано, а затем в конструкторе вы инициализируете переменную...

Функциональная разница может возникнуть в тот момент, когда вы добавите еще один конструктор, в этом случае переменная b должна быть инициализирована даже в этом конструкторе, иначе будет огромная разница.

В первом случае у вас инициализирована переменная независимо от того, сколько конструкторов вы реализуете...

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

person aleroot    schedule 12.01.2014
comment
Но это НЕСТАТИЧЕСКАЯ переменная-член. В тот момент, когда я создам экземпляр A, эта переменная будет инициализирована внутри или вне конструктора. Возможно, вы имеете в виду, что разница в порядке операций? Сначала инициализируется переменная b, а затем вызывается метод A() или наоборот? - person barak manos; 12.01.2014

В целом ничем не отличается (имеется в виду, что объявление снаружи и внутри конструктора будет вести себя по-разному). Просто напомните, что инициализация снаружи будет выполняться первой, прежде чем войти в какой-то конкретный конструктор. Например:

class A {
  int a = 3;
  public A() {
     a = 4;  // now a = 4. not 3
  }
}

Но я часто использую их с другой целью:

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

  2. Когда у вас много перегружаемых конструкторов, а некоторые переменные всегда объявляют одно и то же. Простая «переменная состояния», такая как isExist isEmpty... Я часто инициализирую вне области действия конструктора. Итак, все другие конструкторы не делают то же самое.

person hqt    schedule 12.01.2014

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

person Federico Ponzi    schedule 12.01.2014

Между этими подходами есть одно небольшое различие!

Когда переменная объявлена ​​внутри конструктора, есть шанс, что через некоторое время будет создан второй конструктор, и эта переменная будет неинициализирована. Для борьбы с этим объявите эту переменную как final - если это возможно, конечно;)

Других отличий не существует :)

public class A
{
    private B b;
    public A() {
        b = new B();
    }
    public A(int value) { // second constructor
    }
    ...
}

После использования A a = new A(5); поле b становится null.

person MariuszS    schedule 12.01.2014
comment
будет создан второй конструктор? Что именно это означает? - person barak manos; 12.01.2014
comment
Образец @barakmanos прилагается - person MariuszS; 12.01.2014

Основное отличие заключается в порядке вызовов функций:

  • В первом случае метод B() вызывается перед методом A().
  • Во втором случае метод A() вызывается перед методом B().

Дополнительным отличием является то, что было предложено во всех других ответах...

Если существует конструктор не по умолчанию, который не инициализирует переменную b:

  • В первом случае переменная b будет инициализирована даже при использовании этого конструктора.
  • Во втором случае переменная b не будет инициализирована всякий раз, когда используется этот конструктор.
person barak manos    schedule 12.01.2014