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

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

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

10 ответов

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

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

Всегда.

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

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

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

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

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

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

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

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

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

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

Если вы предоставите конструктор, то 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);
    }
}

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

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

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

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

Любой конструктор в подклассе будет вызывать конструктор без аргументов (или конструктор по умолчанию) родительского класса. если вы определите параметризованный конструктор в родительском классе, то вам придется явно вызывать конструктор родительского класса с помощью ключевого слова 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

или же

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

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 
Другие вопросы по тегам