2016-07-27 4 views
15

Я столкнулся с вопросом, который запрашивает «Что из перечисленного верно в отношении конструктора по умолчанию?»Конструктор по умолчанию не инициализирует члены экземпляра класса?

и опция «Инициализирует членов экземпляра класса». был неправильным выбором.

Теперь я понимаю, что если у нас есть такой код

Class Test { 
     String name; 
    } 

, то компилятор создает конструктор по умолчанию, который выглядит как

Class Test { 
     String name; 
     Test(){ 
      super(); 
      name = null; 
     } 
    } 

Не конструктор по умолчанию инициализирует имя элемента экземпляра = null?

+1

Возможный дубликат [Java default constructor] (http://stackoverflow.com/questions/4488716/java-default-constructor) –

+2

'class' является строчным в Java. – kamoroso94

ответ

9

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

Согласно specification

  • Каждый класс переменной, переменной экземпляра или компонент массива инициализируется со значением по умолчанию при его создании (§15.9, §15.10.2):
    • Для типа байта , значение по умолчанию равно нулю, то есть значение (byte)0.
    • Для типа short значение по умолчанию равно нулю, то есть значение (short)0.
    • Для типа int значение по умолчанию равно нулю, то есть 0.
    • Для типа long значение по умолчанию равно нулю, то есть 0L.
    • Для типа float значением по умолчанию является положительный ноль, то есть 0.0f.
    • Для типа double значение по умолчанию - положительное ноль, то есть 0.0d.
    • Для символа типа значением по умолчанию является нулевой символ, то есть '\u0000'.
    • Для типа boolean значение по умолчанию: false.
    • Для всех ссылочных типов (§4.3) значение по умолчанию: null.

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

Читать подраздел §15.9.4, чтобы понять, каким образом процесс инициализации осуществляется

+0

Означает ли это, что для хорошо написанных конструкторов, отличных от по умолчанию, ваши члены инициализируются, а затем сразу же меняется их значение? Не кажется очень эффективным. –

+0

@LightnessRacesinOrbit Это не всегда так, что все конструкторы, не относящиеся к умолчанию, будут инициализировать всех членов. _Well написано_ является интересным свойством попробовать и оценить. – Gusdor

+0

@LightnessRacesinOrbit: Я только внес вклад в одну реализацию Java, и это было много лет назад, но так, как мы это делали, было выделение нулевой памяти (а IIRC - обнуленная память gc при уничтожении). Так что да, в некотором смысле это неэффективно по сравнению с C или C++, где есть такая вещь, как неинициализированная память. То, за что вы платите, заключается в том, что на Java нет такой вещи. Но это не так уж плохо, поскольку явным образом присваиваю '0' члену данных' byte', который вот-вот будет перезаписан. Это был «memset», как правило, в потоках с низким приоритетом. Я не знаю, делает ли Oracle то же самое. –

1

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

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

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

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


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

3

Не является конструктором по умолчанию, инициализирующим член экземпляра name = null?

Нет, конструкторы вызываются после все переменные экземпляра инициализируются значениями по умолчанию: 0 или эквивалентное значение для primitive numerical types, false для boolean типа, null для reference types.

4

В полях Java инициализируются до конструктор. Это может быть легко доказано следующим кодом:

public class MyClass { 

    int myField = initMyField(); 

    MyClass(){ 
     System.out.println("ctor"); 
    } 

    static int initMyField() { 
     System.out.println("init field"); 
     return 1; 
    } 
} 

выход

init field 
ctor 

Вы также можете проверить де-скомпилированный код.

+2

-1 это ничего не доказывает. Поскольку неявная 'super()' инициализация может быть соткана внутри, в начале конструктора. –

+0

На самом деле вы показываете другую вещь: инициализация, которую вы показываете, фактически перемещается в блок инициализации класса, где выполняется после начальной инициализации всех параметров (что делает JVM после выделения памяти для объекта) и после выполнения этих двух функций вызывается конструктор. – Falco

+0

'myField',' initMyField'. Обратите внимание на lowerCase. – glglgl

0

Конструктор по умолчанию предоставляет значения по умолчанию для объекта (ов) и обычно создается компилятором, когда явно не определен конструктор. например

class DefaultTest{ 
int id; 
String name; 

void display(){System.out.println(id+" "+name);} 

public static void main(String args[]){ 
DefaultTest s1=new DefaultTest(); 
DefaultTest s2=new DefaultTest(); 
s1.display(); 
s2.display(); 
} 
} 

NB: Там быть не конструктор не определен компилятор генерирует конструктор по умолчанию, который будет присваивать 0 нулевые значения для двух объектов.

-1

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

т.е.

Integer nonPrim; 
int prim; 

затем после создания объекта nonPrim == null; prim == 0

Благодарности

1

Он делает. Хотя вопрос основан скорее на использовании.

public class Main { 
    String x; 

    Main() { 
     x = "Init"; 
    } 

    @Override 
    public String toString() { 
     return x; 

    } 

    public static void main(String[] args) { 
     System.out.println(new Main()); 
    } 

} 

Ouput:

Init 
0

Всякий раз, когда мы выполняем класс Java, первый статический контроль потока будет выполняться.В потоке Static Control, если мы создаем объект, то следующие шаги будут выполнены (в указанном порядке) в качестве части Inatance потока управления:

  1. Идентификация членов экземпляра (переменной экземпляра и экземпляра блоков) из сверху вниз.
  2. Выполнение присвоений переменных экземпляра и блоков экземпляров.
  3. Выполнение конструктора.

Таким образом, в приведенном выше коде переменная экземпляра «имя» уже присвоена нулевому значению (значение по умолчанию для ссылочных типов) еще до выполнения constuctor.

Смежные вопросы

 Смежные вопросы