테마
Java 클래스·상속·생성자
클래스(class)는 데이터와 동작을 묶은 설계도이고, 상속(inheritance)은 기존 클래스의 멤버를 물려받아 새 클래스를 만드는 방법이다. Java 출력 문제는 생성자가 어떤 순서로 불리는지, 부모 타입 변수로 부른 메서드가 누구의 것인지, static 변수가 객체 사이에서 공유되는지에서 갈린다.
생성자와 this·super
생성자(constructor)는 new로 객체를 만들 때 한 번 실행되어 필드를 초기화하는 특별한 메서드다. 이름이 클래스와 같고 반환형이 없다. 생성자를 하나도 적지 않으면 컴파일러가 매개변수 없는 기본 생성자(default constructor)를 넣어 주지만, 하나라도 적으면 넣어 주지 않는다. 자식 객체를 만들면 부모 생성자가 먼저 끝난 뒤 자식 생성자 본문이 실행된다. 자식 생성자 첫 줄에 super(...)나 this(...)가 없으면 컴파일러가 super()를 넣기 때문이다.
this(...): 같은 클래스의 다른 생성자를 부른다.this.x는 자기 객체의 필드다.super(...): 부모 생성자를 부른다.super.m()은 부모 쪽 메서드를 부른다.
java
class A { A(int n) { System.out.print("A" + n); } }
class B extends A {
B() { this(5); System.out.print("B"); }
B(int n) { super(n); System.out.print("b" + n); }
}
// new B() 출력: A5b5Bnew B()는 B()로 들어가지만 첫 줄 this(5)가 B(int)를, 그 첫 줄 super(5)가 A(int)를 부른다. 가장 안쪽인 A부터 출력하고 되돌아오며 b5, B가 찍힌다.
오버로딩과 오버라이딩
| 구분 | 오버로딩(overloading) | 오버라이딩(overriding) |
|---|---|---|
| 위치 | 같은 클래스 안(물려받은 메서드 포함) | 부모와 자식 사이 |
| 이름 | 같음 | 같음 |
| 매개변수 | 개수나 형이 다름 | 똑같음 |
| 결정 시점 | 컴파일할 때 | 실행할 때 |
오버로딩(overloading)은 이름은 같고 매개변수가 다른 메서드를 여러 개 두는 것이다. 자식이 부모에게 물려받은 show() 옆에 show(int n)을 새로 두는 것도 오버로딩이다. 반환형만 다른 것은 오버로딩이 아니다. 오버라이딩(overriding)은 부모 메서드를 자식이 같은 모양으로 다시 정의하는 것이다.
동적 바인딩과 static
Parent o = new Child();처럼 부모 타입 변수에 자식 객체를 담으면, 인스턴스(instance) 메서드는 실제 객체(자식)의 것이 실행된다. 실행 시점에 실제 객체를 보고 메서드를 고르는 이 방식을 동적 바인딩(dynamic binding)이라 한다. 반대로 필드와 static 메서드는 변수의 선언 타입을 따라 컴파일할 때 정해진다(정적 바인딩, static binding). 그래서 o.v는 부모의 필드 값이 나온다. 또 부모 타입 변수로는 부모에 선언된 메서드만 부를 수 있다. 자식에만 있는 메서드를 o.으로 부르면 컴파일 오류다.
동적 바인딩은 부모 생성자 안에서도 일어난다. 부모 생성자가 setup()을 부르는데 자식이 setup()을 재정의해 두었다면, 자식 객체를 만드는 중에는 자식의 setup()이 실행된다. "부모 생성자 안이니 부모 메서드"라고 생각하면 틀린다.
static이 붙은 필드는 객체마다 따로 생기지 않고 클래스에 하나만 있어 모든 객체가 공유한다. 객체 수를 세는 카운터가 대표적이다. 그래서 static 필드는 클래스명.필드로 부르는 것이 원칙이다.
시험 포인트
- 생성자 순서: 부모 생성자 → 자식 생성자.
this()·super()는 생성자 첫 줄에만.1 - 같은 이름·다른 매개변수 → 오버로딩, 부모 메서드 재정의 → 오버라이딩.
- 부모 타입 변수로 부른 인스턴스 메서드는 자식 것, 필드·static 메서드는 선언 타입 것.
- static 필드는 모든 객체가 공유한다.
- 부모 생성자가 부른 메서드도 자식이 재정의했으면 자식 것이 실행된다.
참고
시험이 따르는 전통적인 규칙이다. Java 25부터는 생성 중인 객체를 참조하지 않는 문장이면
super(...)·this(...)앞에 둘 수 있다(JEP 513, Java Enhancement Proposal, 자바 개선 제안). 명시적 호출이 없으면super()가 자동으로 들어가는 규칙은 그대로다. ↩︎
