생성자 문서의 구현 코드다.
// 실행: docker run --rm -v "$PWD":/w -w /w eclipse-temurin:21-jdk java 15_java-constructor_impl.java
// (JDK 21. 파일 이름이 숫자로 시작해 public 클래스를 두지 않는다. 맨 위 클래스의 main이 돈다.)
// 문서 「생성자」의 예제 출력과 카드 답을 실제 실행 결과와 비교한다.
import java.util.Arrays;
class ConstructorCheck {
// 문서의 생성자 세 개. 넘긴 값의 개수와 타입으로 생성자가 골라진다
static void overloading() {
int[] grades = {90, 85, 88};
Student s1 = new Student();
Student s2 = new Student("Alice");
Student s3 = new Student("Bob", grades);
System.out.println(s1.name + " " + Arrays.toString(s1.grades));
System.out.println(s2.name + " " + Arrays.toString(s2.grades));
System.out.println(s3.name + " " + Arrays.toString(s3.grades));
}
// this를 빼먹으면 매개변수에 매개변수를 넣는 꼴이 된다
static void missingThis() {
Wrong w = new Wrong("Alice");
Right r = new Right("Alice");
System.out.println(w.name);
System.out.println(r.name);
}
// this(...)로 다른 생성자에게 일을 넘긴다
static void thisCall() {
Scv a = new Scv();
Scv b = new Scv("SCV-7");
System.out.println(a.name + " " + a.health);
System.out.println(b.name + " " + b.health);
}
// new를 할 때마다 다른 객체가 생긴다
static void twoObjects() {
Scv a = new Scv();
Scv b = new Scv();
System.out.println(a == b);
}
// 카드 C3: 필드 초기값 → 생성자 본문 순서
static void card() {
Tank t = new Tank(3);
System.out.println(t.fuel);
}
public static void main(String[] args) {
check("overloading", capture(ConstructorCheck::overloading),
"null null\nAlice null\nBob [90, 85, 88]\n");
check("missing this", capture(ConstructorCheck::missingThis), "null\nAlice\n");
check("this(...)", capture(ConstructorCheck::thisCall), "SCV 45\nSCV-7 45\n");
check("two objects", capture(ConstructorCheck::twoObjects), "false\n");
check("card C3", capture(ConstructorCheck::card), "10\n13\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 Student {
public String name;
public int[] grades;
// Constructor 1
public Student() {}
// Constructor 2
public Student(String name) {
this.name = name;
}
// Constructor 3
public Student(String name, int[] grades) {
this.name = name;
this.grades = grades;
}
}
class Wrong {
String name;
Wrong(String name) {
name = name; // 양쪽 다 매개변수 name이다. 필드는 그대로 null
}
}
class Right {
String name;
Right(String name) {
this.name = name; // 왼쪽은 이 객체의 필드, 오른쪽은 매개변수
}
}
class Scv {
String name;
int health;
Scv() {
this("SCV");
}
Scv(String name) {
this(name, 45);
}
Scv(String name, int health) {
this.name = name;
this.health = health;
}
}
class Tank {
int fuel = 10;
Tank(int extra) {
System.out.println(fuel);
fuel = fuel + extra;
}
}