[Java] 21. super란? (super vs this vs this())
super란?
✅ 부모 클래스를 가리키는 키워드로 자식 클래스가 부모 클래스의 멤버(변수, 메서드, 생성자)를 참조할 때 사용하는 키워드입니다.
자식 클래스는 부모 클래스의 속성과 기능을 상속받기 때문에, 필요할 때 부모의 메서드나 생성자에 접근할 수 있어야 합니다.
이럴 때 사용하는 것이 바로 super입니다!
사용 예시
super 키워드를 언제 사용해야 할까요?
다음과 같은 세 가지 상황에서 사용할 수 있습니다!
상황 | 호출 방법 |
부모의 생성자를 호출할 때 | super() |
부모의 변수에 접근할 때 | super.변수명 |
부모의 메서드를 호출할 때 | super.메서드명() |
* super() – 부모 클래스의 생성자 호출
자식 클래스가 생성될 때, 부모 클래스의 생성자를 먼저 호출하고 싶을 때 사용합니다.
* Parent1 클래스 (부모클래스)
class Parent1 {
public Parent1(String msg) {
System.out.println("부모 생성자: " + msg);
}
}
* Child1 클래스 (자식클래스)
class Child1 extends Parent1 {
public Child1() {
super("Hello!"); // 부모 생성자 호출
System.out.println("자식 생성자 실행");
}
}
* 실행 클래스
public class Main1 {
public static void main(String[] args) {
new Child1();
}
}
- 출력 결과 -
부모 생성자: Hello!
자식 생성자 실행
* super.변수명 – 부모 클래스의 변수 사용
부모와 자식이 같은 이름의 변수를 가질 때, 부모의 값을 명확히 참조할 수 있습니다.
* Parent2 클래스 (부모클래스)
class Parent2 {
String name = "부모";
}
* Child2 클래스 (자식클래스)
class Child2 extends Parent2 {
String name = "자식";
public void printNames() {
System.out.println("this.name = " + this.name); // 자식
System.out.println("super.name = " + super.name); // 부모
}
}
* 실행 클래스
public class Main2 {
public static void main(String[] args) {
Child2 c = new Child2();
c.printNames();
}
}
- 출력 결과 -
this.name = 자식
super.name = 부모
* super.메서드() – 부모 클래스의 메서드 호출
자식 클래스에서 메서드를 오버라이딩했지만, 부모의 원래 기능도 함께 사용하고 싶을 때 사용합니다.
* Animal 클래스 (부모클래스)
class Animal {
public void sound() {
System.out.println("동물이 소리를 냅니다.");
}
}
* Dog 클래스 (자식클래스)
class Dog extends Animal {
@Override
public void sound() {
super.sound(); // 부모의 sound() 호출
System.out.println("멍멍!");
}
}
* 실행 클래스
public class Main3 {
public static void main(String[] args) {
Dog dog = new Dog();
dog.sound();
}
}
- 출력 결과 -
동물이 소리를 냅니다.
멍멍!
주의사항
- super()는 반드시 생성자의 첫 줄에만 사용 가능
- 부모에 기본 생성자가 없을 경우, 반드시 명시적으로 호출해야 함
💡 명시적으로 호출한다는 뜻?
개발자가 직접 코드를 써서 호출하는 것을 의미합니다.
예를 들어, 부모 클래스에 있는 생성자를 호출할 때, 우리가 super("값");처럼 직접 super()를 써서 부모 생성자를 호출하는 것이 바로 "명시적 호출"입니다.
예시
* Parent3 클래스 (부모클래스)
class Parent3 {
public Parent3(String name) {
System.out.println("부모 생성자: " + name);
}
}
* Child3 클래스 (자식클래스)
class Child3 extends Parent3 {
public Child3() {
super("홍길동"); // 부모 생성자 명시적으로 호출
System.out.println("자식 생성자");
}
}
* 실행 클래스
public class Main4 {
public static void main(String[] args) {
new Child3();
}
}
- 출력 결과 -
부모 생성자: 홍길동
자식 생성자
👉 여기서 super("홍길동")은 명시적 호출입니다.
부모 클래스에 기본 생성자가 없기 때문에 우리가 직접 부모 생성자를 호출해야 합니다.
💡 암시적으로 호출한다는 뜻?
자바가 자동으로 호출해주는 것을 의미합니다.
예를 들어, 부모 클래스에 기본 생성자가 있다면, 자식 클래스에서 아무것도 작성하지 않아도 자바가 자동으로 super()를 호출해줍니다.
예시
* Parent4 클래스 (부모클래스)
class Parent4 {
public Parent4() {
System.out.println("부모 생성자");
}
}
* Child4 클래스 (자식클래스)
class Child4 extends Parent4 {
public Child4() {
// 자바가 자동으로 super(); 를 호출합니다.
System.out.println("자식 생성자");
}
}
* 실행 클래스
public class Main5 {
public static void main(String[] args) {
new Child4();
}
}
- 출력 결과 -
부모 생성자
자식 생성자
👉 여기서는 super()를 명시적으로 쓰지 않아도 자바가 자동으로 super()를 호출합니다.
부모 클래스에 기본 생성자가 있으므로 자식 클래스에서 super()를 자동으로 호출합니다.
❗ 부모 클래스에 기본 생성자가 없으면?
만약 부모 클래스에 기본 생성자가 없으면, 자바가 자동으로 super()를 호출할 수 없습니다.
그럴 때는 우리가 명시적으로 super(...)를 호출해야 합니다!
예시
* Parent5 클래스 (부모클래스)
class Parent5 {
public Parent5(String name) {
System.out.println("부모 생성자: " + name);
}
}
* Child5 클래스 (자식클래스)
class Child5 extends Parent5 {
public Child5() {
// super(); ❌ 기본 생성자가 없어서 자동 호출 불가
super("홍길동"); // ⭕ 명시적으로 호출해야 함!
System.out.println("자식 생성자");
}
}
* 실행 클래스
public class Main6 {
public static void main(String[] args) {
new Child5();
}
}
- 출력 결과 -
부모 생성자: 홍길동
자식 생성자
👉 이때는 자식 클래스에서 super("홍길동")처럼 직접 부모 생성자를 호출해야 합니다!
요약
- 명시적 호출: 내가 직접 super()를 작성해서 부모 생성자를 호출하는 것
- 암시적 호출: 자바가 자동으로 super()를 호출해주는 것 (부모 클래스에 기본 생성자가 있을 때)
super, this, this()의 차이점
super vs this
super와 this는 비슷해 보이지만, 그 용도와 가리키는 대상을 잘 구분해야 합니다.
키워드 | 의미 | 사용 위치 |
super | 부모 클래스 | 자식 클래스에서 부모 클래스의 멤버(변수, 메서드)를 참조할 때 |
this | 현재 객체(자기 자신) | 자식 클래스에서 현재 객체(자기 자신)를 참조할 때 |
사용 예시
* Parent6 클래스 (부모클래스)
class Parent6 {
String name = "부모";
void sayHello() {
System.out.println("부모 인사: 안녕!");
}
}
* Child6 클래스 (자식클래스)
class Child6 extends Parent6 {
String name = "자식";
void sayHello() {
System.out.println("자식 인사: Hello!");
}
void showInfo() {
System.out.println("this.name = " + this.name); // 자식 name
System.out.println("super.name = " + super.name); // 부모 name
this.sayHello(); // 자식 메서드
super.sayHello(); // 부모 메서드
}
}
* 실행 클래스
public class Main6 {
public static void main(String[] args) {
Child6 child6 = new Child6();
child6.showInfo();
}
}
- 출력 결과 -
this.name = 자식
super.name = 부모
자식 인사: Hello!
부모 인사: 안녕!
super() vs this()
- super()는 부모 생성자 호출
- this()는 자기 자신의 생성자 호출
사용 예시
* Parent7 클래스 (부모클래스)
class Parent7 {
public Parent7(String msg) {
System.out.println("부모 생성자: " + msg);
}
}
* Child7 클래스 (자식클래스)
class Child7 extends Parent7 {
public Child7() {
this("기본값"); // 자기 자신의 다른 생성자 호출
}
public Child7(String msg) {
super("From Child: " + msg); // 부모 생성자 호출
}
}
* 실행 클래스
public class Main7 {
public static void main(String[] args) {
new Child7();
}
}
- 출력 결과 -
부모 생성자: From Child: 기본값
요약
- this
→ 변수/메서드 이름이 겹칠 때 나 자신을 명확하게 표현
→ 하나의 생성자에서 다른 생성자 호출할 때 사용 (this()) - super
→ 부모 클래스의 변수/메서드 호출 시 사용
→ 부모 생성자 호출 시 사용 (super()는 반드시 생성자의 첫 줄!)
읽어주셔서 감사합니다 😊