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

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

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


person user42155    schedule 08.02.2009    source источник
comment
Нужно ли редактировать сообщение в строке, которая предполагает, что Конструктор инициализирует все переменные экземпляра класса (если они есть) с некоторыми значениями по умолчанию (0, null или false). вводить читателя в заблуждение?   -  person Srujan Kumar Gulla    schedule 09.01.2013


Ответы (11)


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

  2. Если какой-либо конструктор явно не вызывает конструктор super или this в качестве своего первого оператора, автоматически добавляется вызов super ().

Всегда.

person paulmurray    schedule 09.02.2009
comment
Ссылки не работают (спасибо Oracle), вот новые: docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.8.9 и docs.oracle.com/javase/specs/jls/se7/html /jls-8.html#jls-8.8.7 - person Stoffe; 27.08.2012
comment
@Stoffe: Я предложил отредактировать ссылки, благодаря вашим комментариям. Вы можете заработать репутацию, предлагая правки, так почему бы не сделать это в будущем? - person Flimm; 26.03.2013
comment
Я бы добавил, что в случае 2 вызов super не имеет параметров. - person LuxDie; 05.12.2017

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

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

person starblue    schedule 08.02.2009
comment
Да, я только что понял это, потыл ниже указал на это. Но как (и когда) тогда инициализируются поля? (см. мой комментарий к ответу Потыла). - person user42155; 08.02.2009
comment
Может быть, когда я создаю объект, Java автоматически предоставляет значения по умолчанию? Но опять же, мы создаем объекты с помощью конструкторов, не так ли? - person user42155; 08.02.2009
comment
Да, исследование заняло некоторое время. инициализация. - person starblue; 08.02.2009
comment
Спасибо, я тоже нашел хорошую статью именно об этом - инициализации на Java, здесь: javaworld.com/javaworld/jw-03-1998/ - person user42155; 08.02.2009
comment
Обратите внимание, что конструктор по умолчанию для Object не пустой, он родной. Конструктор обычно отвечает за такие вещи, как выделение памяти. - person chrylis -cautiouslyoptimistic-; 13.02.2015
comment
@chrylis Нет, это неправильно. В исходном коде java.lang.Object нет объявления конструктора (я только что посмотрел). Спецификация языка Java говорит в 8.8.9: Если объявляемый класс является первичным классом Object, то конструктор по умолчанию имеет пустое тело. Выделение памяти осуществляется виртуальной машиной. - person starblue; 14.02.2015

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

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

person Peter Lawrey    schedule 08.02.2009
comment
Под пустым конструктором вы имеете в виду конструктор по умолчанию, верно? - person user42155; 08.02.2009
comment
А что, если у родителя нет конструктора по умолчанию? - person user42155; 08.02.2009
comment
Здесь я имею в виду конструктор без аргументов. Обычно конструктор по умолчанию - это тот, который вообще не определен. Вы можете определить конструктор без аргументов. - person Peter Lawrey; 08.02.2009
comment
Если у родителя нет конструктора без аргументов, вы должны вызвать super (...) для допустимого конструктора в суперклассе. - person Peter Lawrey; 08.02.2009
comment
Вы имеете в виду действительный конструктор в классе SUB (производном)? - person user42155; 08.02.2009
comment
Кстати, я думаю, мы вызываем конструктор по умолчанию, если он не имеет аргументов (параметров) - неважно, определяете ли вы его, или Java. (?) - person user42155; 08.02.2009
comment
Кажется, я ошибаюсь - конструктор без параметров (или аргументов) называется конструктором без аргументов, а конструктор по умолчанию - это тот, который автоматически предоставляется Java, если вы не пишете конструктор в классе. Это конструктор без аргументов. Я читал это: - person user42155; 08.02.2009
comment
здесь: javaworld.com/javaworld/ jw-03-1998 / - person user42155; 08.02.2009

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

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

person Abhishek Nair    schedule 29.11.2012
comment
Я думаю, это должно быть хорошей практикой всегда помещать туда конструктор по умолчанию, если вы хотите перегруженные конструкторы. - person engineer; 07.01.2013

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

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

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

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

person Sergey Kalinichenko    schedule 13.02.2015
comment
ссылка на ссылку: docs.oracle .com / javase / specs / jls / se8 / html / jls-8.html # jls-8.8.9. - person cellepo; 25.08.2016
comment
что вы имеете в виду, когда даете классу конструктор, доступ к конструктору по умолчанию его суперкласса теряется. ? - person rimalroshan; 12.11.2018

Если вы предоставите конструктор, 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);
    }
}
person potyl    schedule 08.02.2009
comment
Это интересно! Я довольно долго жил с предположением, что если вы не инициализируете переменные экземпляра в конструкторе, то Java делает это в конструкторе по умолчанию. Итак, как в этом случае инициализируются переменные? - person user42155; 08.02.2009
comment
Здесь я нашел хорошую статью об инициализации на Java, отвечая на свой вопрос: javaworld.com/javaworld/jw-03-1998/ - person user42155; 08.02.2009
comment
Создание экземпляра объекта требует, чтобы оператор new выделял память и вызывал конструктор (используемый для начальной логики). Наши конструкторы заботятся только о последнем. Я предполагаю, что первая часть заботится об инициализации элементов данных по умолчанию при распределении памяти. - person potyl; 08.02.2009

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

person Muthu N    schedule 23.06.2011

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

person Ashish    schedule 23.03.2017

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

person Thusitha    schedule 26.01.2011
comment
... создать объект без конструктора Мы должны объявить ... = ›... создать объект без каких-либо аргументов конструктора аргументов, мы должны объявить ... - person Bert F; 26.01.2011

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

person Shubhamhackz    schedule 30.08.2017

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

class Alpha 
{ 
    Alpha(int s, int p) 
    { 
        System.out.println("base");
    }

} 

public class SubAlpha extends Alpha 
{ 
    SubAlpha() 
    { 
        System.out.println("derived"); 
    } 
    public static void main(String[] args) 
    { 
        new SubAlpha(); 
    } 
}

Приведенный выше код выдаст ошибку компиляции:

prog.java:13: error: constructor Alpha in class Alpha cannot be applied to given types;
    { 
    ^
  required: int,int
  found: no arguments
  reason: actual and formal argument lists differ in length
1 error

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

Теперь, чтобы решить эту проблему, либо вызовите параметризованный конструктор следующим образом:

class Alpha 
{ 
    Alpha(int s, int p) 
    { 
        System.out.println("base");
    }

} 

public class SubAlpha extends Alpha 
{ 
    SubAlpha() 
    { 
        super(4, 5); // calling the parameterized constructor of parent class
        System.out.println("derived"); 
    } 
    public static void main(String[] args) 
    { 
        new SubAlpha(); 
    } 
}

Вывод

base
derived

or

определите конструктор без аргументов в родительском классе следующим образом:

class Alpha 
{ 
    Alpha(){

    }
    Alpha(int s, int p) 
    { 
        System.out.println("base");
    }

} 

public class SubAlpha extends Alpha 
{ 
    SubAlpha() 
    { 
        System.out.println("derived"); 
    } 
    public static void main(String[] args) 
    { 
        new SubAlpha(); 
    } 
}

вывод

derived 
person Anmol Middha    schedule 19.05.2019