Java задача из сертификационного теста

Java

Простая задачка с двумя (а может у кого и больше) «заковырками». Была почерпнута из книги по подготовке к сертификационному экзамену Java SE 8 Oracle Certified Associate (OCA).

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

class Base {
    protected int i;
    Base() { add(1); }
    void add(int v) { i += v; }
    void print() { System.out.println(i); }
}

class Extension extends Base {
    Extension() { add(2); }
    void add(int v) { i += v*2; }
}

public class Qd073 {
    public static void main(String[] args) {
        bogo(new Extension());
    }
    static void bogo(Base b) {
        b.add(8);
        b.print();
    }
}

Что будет выведено на экран?

Предлагаемые варианты ответов: 9, 11, 13, 21, 22.

Верный ответ – 22.

Решение:

Первым делом создается объект класса Extension. Для этого вызывается конструктор без параметров Extension(), однако в нем первой строкой не идет вызов конструктора суперкласса, поэтому компилятор сам дописывает его и фактически конструктор Extension() выглядит так:

Extension() { 
    super(); 
    add(2); 
}

Внутри конструктора Base() происходит вызов метода add(1). Поскольку этот метод переопределен в Extension, то вызывается именно он.

Дальше вызывается метод add(2), при этом i = 2. В итоге в метод bogo передается объект класса Extension значение i которого равно 6.

В bogo происходит вызов метода add(8) который так же связан с объектом класса Extension. В итоге i = 6 + 8 * 2 = 22, что и выводится на печать.

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

class Base {
    int i;
    Base() {
        System.out.println("Начало конструктора Base: i = " + i);
        add(1);
        System.out.println("Конец конструктора Base: i = " + i);
    }
    void add(int v) {
        System.out.println("Начало метода add внутри Base: i, v = " + i + ", " + v);
        i += v;
        System.out.println("Конец метода add внутри Base: i, v = " + i + ", " + v);
    }
    void print() {
        System.out.println(i);
    }
}
class Extension extends Base {
    Extension() {
        System.out.println("Начало конструктора Extension: i = " + i);
        add(2);
        System.out.println("Конец конструктора Extension: i = " + i);
    }
    void add(int v) {
        System.out.println("Начало метода add внутри Extension: i, v = " + i + ", " + v);
        i += v*2;
        System.out.println("Конец метода add внутри Extension: i, v = " + i + ", " + v);
    }
}
public class Qd073 {
    public static void main(String args[]) {
        bogo(new Extension());
    }
    static void bogo(Base b) {
        b.add(8);
        b.print();
    }
}

И посмотреть, что будет выведено на экран.

Начало конструктора Base: i = 0
Начало метода add внутри Extension: i, v = 0, 1
Конец метода add внутри Extension: i, v = 2, 1
Конец конструктора Base: i = 2
Начало конструктора Extension: i = 2
Начало метода add внутри Extension: i, v = 2, 2
Конец метода add внутри Extension: i, v = 6, 2
Конец конструктора Extension: i = 6
Начало метода add внутри Extension: i, v = 6, 8
Конец метода add внутри Extension: i, v = 22, 8
22

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

Михаил Миронов

Живу в Нижнем Новгороде, работаю программистом с 2017 года, основная специализация Java, но также хорошо знаю PHP, Python, XML, HTML/CSS.

Добавить комментарий