Простая задачка с двумя (а может у кого и больше) «заковырками». Была почерпнута из книги по подготовке к сертификационному экзамену 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
В итоге задача оказывается очень простой, необходимо только не забывать про вызов конструктора суперкласса и о динамическом связывании.