자바는 수많은 키워드 중에서도 this와 super라는 특별한 키워드를 제공합니다. this는 클래스의 현재 인스턴스(객체 자신)를 나타내는 데 사용되고, super는 해당 클래스가 상속받은 부모(슈퍼) 클래스를 가리키는 데 사용됩니다.
두 키워드는 모두 객체의 멤버에 접근한다는 공통점이 있지만, 용도와 동작 방식에서 중요한 차이점을 가지고 있습니다. 아래 비교표를 통해 핵심 차이를 살펴보겠습니다.
this와 super 비교표
| 번호 | 구분 | this | super |
|---|---|---|---|
| 1 | 의미 및 참조 | 현재 클래스의 인스턴스, 즉 객체 자신을 나타냅니다. | 현재 객체가 상속받은 부모 클래스의 인스턴스 부분을 나타냅니다. |
| 2 | 생성자 호출 | this() 형태로 같은 클래스 내의 다른 생성자(오버로딩된 생성자)를 호출할 수 있습니다. | super() 형태로 부모 클래스의 생성자를 호출할 수 있으며, 반드시 생성자의 첫 번째 문장으로 작성해야 합니다. |
| 3 | 멤버 접근 | 현재 클래스의 필드와 메서드에 접근할 때 사용합니다. 특히 매개변수 이름과 필드 이름이 같을 때 이를 구분하는 용도로 유용합니다. | 부모 클래스의 필드와 메서드에 접근할 때 사용합니다. 오버라이딩된 메서드나 자식 클래스에서 가려진(shadowed) 필드에 접근할 때 유용합니다. |
| 4 | static 컨텍스트 | static 메서드나 static 블록에서는 사용할 수 없습니다. static 컨텍스트에는 인스턴스(this)가 존재하지 않기 때문에 사용 시 컴파일 오류가 발생합니다. | 마찬가지로 static 메서드나 static 블록에서는 사용할 수 없으며, 사용 시 컴파일 오류가 발생합니다. |
this와 super 활용 예제
다음 예제는 상속 관계에 있는 두 클래스에서 this(), super(), 그리고 super.를 어떻게 활용하는지 보여줍니다.
Main.java
class A {
public int x, y;
public A(int x, int y) {
this.x = x; // this로 필드와 매개변수를 구분
this.y = y;
}
}
class B extends A {
public int x, y;
public B() {
this(0, 0); // 같은 클래스의 다른 생성자 호출
}
public B(int x, int y) {
super(x + 1, y + 1); // 부모 클래스 생성자 호출
this.x = x;
this.y = y;
}
public void print() {
System.out.println("Base class : {" + x + ", " + y + "}");
System.out.println("Super class : {" + super.x + ", " + super.y + "}");
}
}
public class Main {
public static void main(String[] args) {
B obj = new B();
obj.print();
obj = new B(1, 2);
obj.print();
}
}실행 결과
Base class : {0, 0}
Super class : {1, 1}
Base class : {1, 2}
Super class : {2, 3}예제 해설
기본 생성자 B()가 실행되면 this(0, 0)을 통해 같은 클래스의 B(int, int) 생성자가 호출됩니다. 이 생성자 안에서는 super(x + 1, y + 1)이 먼저 실행되어 부모 클래스 A의 필드에 각각 1과 1이 저장되고, 이후 자식 클래스 B의 필드에는 전달받은 값(여기서는 0과 0)이 저장됩니다.
따라서 print() 메서드에서 x, y는 자식 클래스 B의 필드 값을 출력하고, super.x, super.y는 부모 클래스 A의 필드 값을 출력하게 됩니다. 이처럼 this와 super를 함께 활용하면 상속 관계에서 필드가 서로 가려지는(shadowing) 상황에서도 원하는 값에 정확하게 접근할 수 있습니다.