부모 생성자 호출 문서의 구현 코드다.
// 실행: docker run --rm -v "$PWD":/w -w /w eclipse-temurin:21-jdk java 21_java-super-constructor_impl.java
// (JDK 21. 파일 이름이 숫자로 시작해 public 클래스를 두지 않는다. 맨 위 클래스의 main이 돈다.)
// 문서 「부모 생성자 호출」의 예제 출력과 카드 답을 실제 실행 결과와 비교한다.
class SuperConstructorCheck {
// 자식 생성자 첫 줄에 숨은 super()가 있어 부모 생성자가 먼저 돈다
static void order() {
new Marine();
}
// 세 층이면 맨 위부터 차례로 돈다
static void threeLevels() {
new C();
}
// 부모에 매개변수 없는 생성자가 없으면 super(값)을 직접 쓴다
static void withArgs() {
Firebat f = new Firebat();
System.out.println(f.name + " " + f.health + " " + f.damage);
}
// 힙에 생기는 객체는 하나다. 부모 생성자 안의 this가 바로 그 자식 객체다
static void oneObject() {
Tank t = new Tank();
System.out.println(Vehicle.seen == t);
System.out.println(Vehicle.seenClass);
}
// 카드 C3
static void card() {
new K();
new K(7);
}
public static void main(String[] args) {
check("order", capture(SuperConstructorCheck::order), "Unit()\nMarine()\n");
check("three levels", capture(SuperConstructorCheck::threeLevels), "A()\nB()\nC()\n");
check("with args", capture(SuperConstructorCheck::withArgs), "Firebat 50 8\n");
check("one object", capture(SuperConstructorCheck::oneObject), "true\nTank\n");
check("card C3", capture(SuperConstructorCheck::card), "P\nK\nP7\nK7\n");
System.out.println("ALL CHECKS PASSED");
}
static String capture(Runnable r) {
java.io.PrintStream old = System.out;
java.io.ByteArrayOutputStream buf = new java.io.ByteArrayOutputStream();
System.setOut(new java.io.PrintStream(buf));
try { r.run(); } finally { System.setOut(old); }
return buf.toString();
}
static void check(String name, String got, String want) {
if (!got.equals(want)) throw new AssertionError(name + "\n--- got ---\n" + got + "--- want ---\n" + want);
System.out.print("[" + name + "]\n" + got);
}
}
class Unit {
Unit() {
System.out.println("Unit()");
}
}
class Marine extends Unit {
Marine() {
// 여기에 컴파일러가 super(); 를 넣는다
System.out.println("Marine()");
}
}
class A { A() { System.out.println("A()"); } }
class B extends A { B() { System.out.println("B()"); } }
class C extends B { C() { System.out.println("C()"); } }
class Infantry {
String name;
int health;
Infantry(String name, int health) { // 매개변수 없는 생성자가 없다
this.name = name;
this.health = health;
}
}
class Firebat extends Infantry {
int damage;
Firebat() {
super("Firebat", 50);
this.damage = 8;
}
}
class Vehicle {
static Object seen;
static String seenClass;
Vehicle() {
seen = this;
seenClass = getClass().getSimpleName();
}
}
class Tank extends Vehicle {
}
class P {
P() { System.out.println("P"); }
P(int x) { System.out.println("P" + x); }
}
class K extends P {
K() { System.out.println("K"); }
K(int x) {
super(x);
System.out.println("K" + x);
}
}