2009-02-08 3 views
50

У меня вопрос о конструкторах по умолчанию и наследовании в Java.Конструкторы и наследование по умолчанию в Java

Как правило, если вы пишете класс и не включаете какой-либо конструктор, Java автоматически предоставляет вам конструктор по умолчанию (один без параметров), который инициализирует все переменные экземпляра класса (если они есть) с некоторыми значениями по умолчанию (0, null или false). Однако, если вы пишете конструктор с некоторыми параметрами и не создаете конструктор по умолчанию, то Java не предоставляет конструктор по умолчанию. Мой вопрос: что происходит с классами, которые наследуются от других классов - если я пишу конструктор с некоторыми параметрами в них, но не включаю конструктор по умолчанию, наследуют ли они конструктор по умолчанию суперкласса?

+1

ли пост необходимости редактирование строки, предполагающее, что «Constructor инициализирует все переменные экземпляра класса (если они есть) с некоторыми значениями по умолчанию (0, null или false)». вводящий в заблуждение читателя? –

ответ

51

Конструкторы не наследуются.

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

+1

Да, я только что понял это, ниже показал ниже. Но как (и когда) являются полями, инициализированными тогда? (пожалуйста, см. мой комментарий на ответ Потиля). – user42155

+0

В этом случае, когда я создаю объект, Java автоматически дает значения по умолчанию? Но опять же, мы создаем объекты с конструкторами, не так ли? – user42155

+0

Да, потребовалось время, чтобы провести исследование w.r.t. инициализация. – starblue

10

Если вы не используете super (...), конструктор вызывает пустой конструктор его родителя. Примечание: Это делается на всех ваших классах, даже те, которые расширяют Object.

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

+0

С «пустым конструктором» вы имеете в виду конструктор по умолчанию, правильно? – user42155

+0

А что, если у родителя нет конструктора по умолчанию? – user42155

+0

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

3

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

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

public class Test { 

    public String s; 
    public int i; 

    public Test(String s, int i) { 
     this.s = s; 
     this.i = i; 
    } 

    public Test(boolean b) { 
     // Empty on purpose! 
    } 

    public String toString() { 
     return "Test (s = " + this.s + ", i = " + this.i + ")"; 
    } 

    public static void main (String [] args) { 
     Test test_empty = new Test(true); 
     Test test_full = new Test("string", 42); 
     System.out.println("Test empty:" + test_empty); 
     System.out.println("Test full:" + test_full); 
    } 
} 
+0

Это интересно! Я довольно долго жил с предположением, что если вы не инициализируете переменные экземпляра в конструкторе, то Java делает это в конструкторе по умолчанию. Итак, в этом случае, как инициализируются переменные? – user42155

+0

Здесь я нашел хорошую статью об инициализации в Java, отвечая на мой вопрос: http://www.javaworld.com/javaworld/jw-03-1998/jw-03-initialization.html?page=1 – user42155

+0

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

59
  1. Если вы не сделаете конструктор, the default empty constructor is automatically created.

  2. Если какой-либо конструктор явно не вызывает супер или этот конструктор в качестве своего первого оператора, a call to super() is automatically added.

Всегда.

+2

Ссылки сломаны (спасибо, Oracle), вот новые: http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.8.9 и http : //docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.8.7 – Stoffe

+1

@Stoffe: Я предложил изменить исправление ссылок благодаря вашим комментариям. Вы можете получить репутацию, предлагая изменения, так почему бы не сделать это в будущем? – Flimm

+0

Я бы добавил, что в случае 2 вызов super не имеет параметров. – LuxDie

1

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

+0

«... создать объект без какого-либо конструктора. Мы должны объявить ...» => «... создать объект без каких-либо конструкторов ** аргументов **, мы должны объявить ...» –

2

Thumb Rule - это то, что Sub Class должен вызывать любой конструктор из базового класса. поэтому, если у вас нет значения по умолчанию, вызовите существующий из подкласса.другой мудрый реализации пустой сопзЬ в базовом классе, чтобы избежать проблемы компиляции

6

Основным правилом является вызов (или вызов) в конструктор должен быть первым оператором, который JVM должен выполнить,

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

+0

Я предполагаю, что он должен быть хорошей практикой всегда ставить конструктор по умолчанию там, если вы хотите «перегруженные» конструкторы. – lwpro2

5

Раздел 8.8.9 из спецификации языка Java объясняет подробно, что происходит:

Если класс не содержит конструктор деклараций, то конструктор по умолчанию неявно объявляется. Форма конструктора в по умолчанию для верхнего уровня класса, класса члена или локального класса выглядит следующим образом:

  • Конструктор по умолчанию имеет тот же доступ, как класс (§6.6).
  • конструктор по умолчанию не имеет формальные параметров, за исключением незакрытого внутреннего класса членов, где конструктор по умолчанию неявно объявляет один формальный параметра, представляющего сразу охватывающий экземпляр класса (§8.8.1, §15.9. 2, §15.9.3).
  • Конструктор по умолчанию не имеет предложений бросков.
  • Если объявляемый класс является искомым объектом класса, то конструктор по умолчанию имеет пустое тело. В противном случае конструктор по умолчанию просто вызывает конструктор суперкласса без аргументов.

Вы можете видеть, что нет никакого наследования здесь происходит: все, что нужно это «компилятор магия» с неявно объявлено конструктором по умолчанию. Спецификация также дает понять, что конструктор по умолчанию добавляется только тогда, когда класс не имеет никаких конструкторов вообще, что означает, что ответ на ваш вопрос «нет»: после предоставления класса конструктору доступ к конструктору по умолчанию его суперкласс потерян.

+0

ссылка ссылка: https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.8.9 – cellepo

2

Ответ на ваш вопрос очень прост. Implicitly (Invisible), первый оператор в любом конструкторе - 'super();' т.е. вызов суперкомпьютера без конструктора параметров, пока вы явно не измените его на нечто вроде «this();», «this (int)», «this (String)», «super (int)», «super (String)) 'и т. д. ' this(); ' является конструктором текущего класса.

0

Там будет ошибка компиляции времени ... потому, что компилятор ищет конструктор по умолчанию он суперкласс, и если его нет ... его ошибки ... и программа не компилируется ...

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