[JAVA] 자바 super 키워드와 super() 메서드

    728x90

    안녕하세요

    로로봉입니다 : )

    오늘은 JAVA에서 super 키워드와 super() 메서드에 대해 알아보도록 하겠습니다.

    this 키워드와 this() 메서드는 클래스 자신의 내부 구성 요소를 호출하는 문법입니다.

    자기 객체를 가리키는 참조 변수명으로 생략했을 때는 컴파일러가 자동으로 추가해서 처리합니다.

    this는 자신의 객체, this() 메서드는 자신의 생성자를 의미합니다.

    반대로 super는 부모의 객체, super()는 부모의 생성자를 의미합니다.

    super와 super() 메서드는 부모 클래스에 대한 것이기 때문에 상속 관계에서만 사용할 수 있습니다.


    1) 부모의 객체를 가리키는 super 키워드

    super 키워드는 부모의 객체를 가리키는 것으로 필드명의 중복 또는 메서드 오버라이딩으로 가려진 부모의 필드 또는 메서드를 호출하기 위해 사용합니다.

    예를 들어 알아보도록 하겠습니다.

    클래스 A에는 abc() 메서드가 1개 있고 이를 상혹한 클래스 B에서는 abc() 메서드를 오버라이딩하고 bcd() 메서드를 생성했습니다.

    새롭게 추가한 bcd() 메서드에서는 abc() 메서드를 호출했습니다. 여기서 호출된 abc() 메서드는 클래스 B의 abc()가 됩니다.

    인스턴스 메서드의 내부에서 모든 필드와 메서드 앞에는 자동으로 컴파일러가 this 키워드를 추가하여 컴파일 하기 때문입니다.

    class A {
       void abc() {
          System.out.println("A 클래스의 abc()");
       }
    }
    class B extends A {
       void abc() {
          System.out.println("B 클래스의 abc()");
       }
       void bcd() {
          abc();		// this.abc();
       }
    }
    
    public class Test {
       public static void main(String[] args) {
          B bb = new B();	// 객체 생성
          
          bb.bcd();		// 메서드 호출
       }
    }

    실행 결과는 "B 클래스의 abc()"가 출려되는 것을 볼 수 있습니다.

    그렇다면 부모 클래스의 abc() 메서드를 자식 클래스에서 어떻게 호출할 수 있는지 알아보겠습니다.

    명시적으로 아래와 같이 super.abc() 라고 작성하면 부모의 abc() 메서드를 호출 할 수 있습니다.

    class A {
       void abc() {
          System.out.println("A 클래스의 abc()");
       }
    }
    class B extends A {
       void abc() {
          System.out.println("B 클래스의 abc()");
       }
       void bcd() {
          super.abc();		// 부모 클래스 객체의 abc() 메서드 호출
       }
    }
    
    public class Test {
       public static void main(String[] args) {
          B bb = new B();
          
          bb.bcd();
       }
    }

    실행해보면 "A 클래서의 abc()" 결과가 출력되는 것을 볼 수 있습니다.

    실제로 이렇게 부모의 메서드를 호출해야 하는 경우는 자주 있습니다.

    class A {
       void init() {
          // 메모리 할당, 화면 세팅, 변수 초기화 등 코드 100줄
       }
    }
    class B extends A {
       void init() {
          // 메모리 할당, 화면 세팅, 변수 초기화 등 코드 100줄
          // 화면 출력 코드 1줄
       }
    }
    class C extends A {
       void init() {
          super.init();
          // 화면 출력 코드 1줄
          
       }
    }

    부모 클래스의 init() 메서드에는 메모리 할당이나 초기화로 100줄정도 되는 코드가 있다고 가정해봅니다.

    자식 클래스(B, C)에서는 부모 클래스의 초기화 기능을 포함하고 화면 출력 코드 1줄만 추가하고 싶은 경우를 가정해보겠습니다.

    우선 B 클래스는 부모 클래스의 init() 메서드 내용을 모두 동일하게 작성하고 화면 출력 코드를 1줄 추가하는 경우이므로 총 101줄을 작성하게 됩니다.

    반면 C 클래스는 super 키워드로 부모 클래스의 init() 메서드를 실행후 화면 출력 코드 1줄을 추가하여 2줄만 작성하여도 B클래스와 동일한 처리를 하게 됩니다.


    2)  부모 클래스의 생성자를 호출하는 super() 메서드

    클래스 A를 상속받아 클래스 B를 생성하고, B() 생성자를 이용해 객체를 생성할 때 항상 부모 클래스 객체가 먼저 생성된다고 했습니다.

    그런데 어떻게 자식 클래스 생성자로 부모 클래스 객체를 먼저 만들 수 있을까요?

    이것이 super() 메서드의 역할입니다.

    super() 메서드는 부모 클래스의 생성자를 호출합니다.

    this()와 마찬가지로 생성자의 내부에서만 사용할 수 있고, 반드시 첫 줄에 와야 합니다.

    this() 메서드도 생성자의 첫 줄에만 올 수 있으므로 이 둘은 1개의 생성자에서 절대로 같이 쓸 수 없습니다.

    class A {
       A() {
          System.out.pringln("A 생성자");
       }
    }
    class B extends A {
       B() {
          super();
          System.out.println("B 생성자");
       }
    }

    B b = new B()와 같이 B() 생성자로 객체를 생성했을 때의 메모리 구조는 아래와 같습니다.

    [ 그림 1 : super() 메서드를 이용한 부모 클래스의 생성자 호출 ]

    B() 생성자를 이용해 객체를 생성할 때는 가장 먼저 super() 메서드를 실행하고 있습니다.

    super()는 부모의 생성자를 호출하는 것이므로 A()가 실행될 것입니다.

    A()생성자의 실행이 완료되면 메모리에는 A 객체가 생성됩니다.

    이후 다시 돌아와 나머지 코드를 실행합니다. B b = new B()와 같이 객체를 생성하면 "A 생성자", "B 생성자" 순으로 출력됩니다.

    여기서 중요한 부분은 모든 생성자의 첫 줄에는 반드시 this() 또는 super()가 있어야 한다는 것입니다.

    아무것도 써주지 않으면 컴파일러는 super()를 자동으로 추가합니다. 즉, 생성자를 호출할 때는 항상 부모 클래스의 생성자가 한 번은 호출된다는 것입니다.

    이게 자식 클래스의 생성자로 객체를 생성할 때 부모 클래스의 객체가 만들어지는 이유입니다.

     

    공감 ♥ + 구독부탁드립니다 : )

    728x90
    반응형

    댓글