← Назад к вопросам

Предсказать вывод: абстрактный класс с конструктором

1.0 Junior🔥 91 комментариев

Условие

Какой результат выведет следующий код?

public abstract class OurAbstractClass {
   public OurAbstractClass() {
      System.out.println("This is abstract class constructor");
   }
}

class OurDemoClass extends OurAbstractClass {
   public OurDemoClass() {
      System.out.println("This is demo class constructor");
   }
   
   public static void main(String[] args) {
      OurDemoClass ourDemoClass = new OurDemoClass();
   }
}

Вопросы

  1. Что выведет программа?
  2. В каком порядке вызываются конструкторы?
  3. Можно ли создать экземпляр абстрактного класса напрямую?

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Предсказание вывода: абстрактный класс с конструктором

Результат выполнения

Программа выведет:

This is abstract class constructor
This is demo class constructor

Почему так?

Это классический пример иерархии конструкторов в наследовании. При создании объекта дочернего класса Java автоматически вызывает конструктор родительского класса.

Порядок вызова конструкторов

  1. Сначала конструктор родителя (OurAbstractClass) — выводит "This is abstract class constructor"
  2. Потом конструктор дочернего класса (OurDemoClass) — выводит "This is demo class constructor"

Это происходит, потому что компилятор Java автоматически добавляет вызов super() в конструктор дочернего класса:

class OurDemoClass extends OurAbstractClass {
   public OurDemoClass() {
      super();  // ← вызов конструктора родителя (компилятор добавляет автоматически)
      System.out.println("This is demo class constructor");
   }
}

Механизм наследования конструкторов

Правило: Конструктор дочернего класса ВСЕГДА вызывает конструктор родительского класса в начале своего выполнения (явно или неявно).

// ❌ Неправильно (скрытый вызов super())
public class Child extends Parent {
    public Child() {
        System.out.println("Child constructor");
    }
}

// ✓ Эквивалентно (явный вызов super())
public class Child extends Parent {
    public Child() {
        super();  // явно
        System.out.println("Child constructor");
    }
}

Важный факт: абстрактный класс имеет конструктор

Вопрос: Можно ли создать объект абстрактного класса напрямую?

// ❌ ОШИБКА! Нельзя инстанцировать абстрактный класс напрямую
OurAbstractClass obj = new OurAbstractClass();  // Compilation error

// ✓ Можно через дочерний класс
OurDemoClass obj = new OurDemoClass();  // OK!

Но! Конструктор абстрактного класса всё равно существует и выполняется при создании дочерних объектов.

Визуализация процесса

Операция: new OurDemoClass()

├─ Начало инициализации объекта
├─ Вызов super() (явно или неявно)
│  └─ Выполнение OurAbstractClass() → выводит сообщение
├─ Выполнение OurDemoClass() → выводит сообщение
└─ Конец инициализации

Пример с явным вызовом super()

public abstract class OurAbstractClass {
   public OurAbstractClass() {
      System.out.println("Abstract class constructor");
   }
}

class OurDemoClass extends OurAbstractClass {
   public OurDemoClass() {
      super();  // явный вызов конструктора родителя
      System.out.println("Demo class constructor");
   }
}

public class Main {
   public static void main(String[] args) {
      OurDemoClass obj = new OurDemoClass();
   }
}

/* Вывод:
Abstract class constructor
Demo class constructor
*/

Цепочка наследования (многоуровневое)

public abstract class GrandParent {
   public GrandParent() {
      System.out.println("1. GrandParent");
   }
}

public abstract class Parent extends GrandParent {
   public Parent() {
      System.out.println("2. Parent");
   }
}

public class Child extends Parent {
   public Child() {
      System.out.println("3. Child");
   }
}

public class Main {
   public static void main(String[] args) {
      new Child();
   }
}

/* Вывод:
1. GrandParent
2. Parent
3. Child
*/

Каждый уровень вызывает super() перед своим конструктором!

С параметрами в конструкторах

public abstract class OurAbstractClass {
   public OurAbstractClass(String msg) {
      System.out.println("Abstract: " + msg);
   }
}

class OurDemoClass extends OurAbstractClass {
   public OurDemoClass(String msg) {
      super(msg);  // передаём параметры родителю
      System.out.println("Demo: " + msg);
   }
}

public class Main {
   public static void main(String[] args) {
      new OurDemoClass("Hello");
   }
}

/* Вывод:
Abstract: Hello
Demo: Hello
*/

Порядок инициализации объекта в Java

1. Выделение памяти для объекта
2. Инициализация полей класса (значения по умолчанию)
3. Вызов конструктора:
   3.1. Неявный вызов super() (если не указан явно)
   3.2. Инициализация блоков инициализации
   3.3. Выполнение тела конструктора

Инициализационные блоки

public abstract class OurAbstractClass {
   {
      System.out.println("Abstract init block");
   }
   
   public OurAbstractClass() {
      System.out.println("Abstract constructor");
   }
}

class OurDemoClass extends OurAbstractClass {
   {
      System.out.println("Demo init block");
   }
   
   public OurDemoClass() {
      System.out.println("Demo constructor");
   }
}

/* Вывод:
Abstract init block      // инициализационный блок родителя
Abstract constructor     // конструктор родителя
Demo init block          // инициализационный блок дочернего класса
Demo constructor         // конструктор дочернего класса
*/

Различие между static инициализацией и конструктором

public abstract class OurAbstractClass {
   static {
      System.out.println("Abstract static block (один раз при загрузке класса)");
   }
   
   {
      System.out.println("Abstract instance block (каждый раз при создании объекта)");
   }
   
   public OurAbstractClass() {
      System.out.println("Abstract constructor");
   }
}

class OurDemoClass extends OurAbstractClass {
   static {
      System.out.println("Demo static block (один раз при загрузке класса)");
   }
   
   {
      System.out.println("Demo instance block");
   }
   
   public OurDemoClass() {
      System.out.println("Demo constructor");
   }
}

/* Вывод при первом new OurDemoClass():
Abstract static block
Demo static block
Abstract instance block
Abstract constructor
Demo instance block
Demo constructor

Вывод при втором new OurDemoClass():
Abstract instance block
Abstract constructor
Demo instance block
Demo constructor
*/

Ключевые выводы

✓ Абстрактный класс может иметь конструктор — он будет вызван при создании дочернего объекта

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

✓ Порядок: всегда сначала родитель, потом дочерний класс

✓ Super() добавляется автоматически, если не указан явно

✓ Инициализационные блоки выполняются до конструктора

✓ Static блоки выполняются один раз при загрузке класса, не при каждом создании объекта

Вывод

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