Java

참조변수와 인스턴스에 따른 method, 변수, static method 참조 결과 비교

1. 알고자 하는 것

- 자바는 객체지향언어로써 다형성을 적용할 수 있다.

- 다형성 : 한 타입의 참조변수로 여러 타입(상속, 구현관계)의 객체를 참조할 수 있도록 하는 것

- Parent와 Child 클래스 관계에서 참조변수와 해당 변수에 할당된 인스턴스의 타입에 따라 호출하는 method, 변수, static method의 참조 결과는 어떻게 되는가?

2. 알게된 것 

class Parent {
    String name = "Parent";

    public void method() {
        System.out.println("Parent Method");
    }

    public void methodOverriding() {
        System.out.println("Parent methodOverriding()");
    }

    public static void staticMethod() {
        System.out.println("Parent Static Method");
    }
}

class Child extends Parent {
    String name = "Child";

    @Override
    public void methodOverriding() {
        System.out.println("Child methodOverriding");
    }
    
    public static void staticMethod() {
        System.out.println("Child Static Method");
    }
}

- 다음과 같은 상속관계에 대해 참조변수 타입을 Parent, Child로 나누어 4가지 경우에 대한 호출을 확인한다.

1. 변수

2. 메서드 (오버라이딩 X)

3. 메서드 (오버라이딩 O)

4. 정적 메서드

public static void main(String[] args) {
        Parent p = new Child();
        Child c = new Child();

        // 1. Variable
        System.out.println("1. Variable");
        System.out.println("p.name = " + p.name);
        System.out.println("c.name = " + c.name);
        System.out.println();

        // 2. Method (Overriding X)
        System.out.println("2. Method (Overriding X)");
        System.out.print("p.method = ");
        p.method();
        System.out.print("c.method = ");
        c.method();
        System.out.println();

        // 3. Method (Overriding O)
        System.out.println("3. Method (Overriding O)");
        System.out.print("p.methodOverriding = ");
        p.methodOverriding();
        System.out.print("c.methodOverriding = ");
        c.methodOverriding();
        System.out.println();

        // 4. Static Method
        System.out.println("4. Static Method");
        System.out.print("p.staticMethod = ");
        p.staticMethod();
        System.out.print("c.staticMethod = ");
        c.staticMethod();
        System.out.println();
    }

 

- 결과는 다음과 같다.

1. Variable
p.name = Parent
c.name = Child

2. Method (Overriding X)
p.method = Parent Method
c.method = Parent Method

3. Method (Overriding O)
p.methodOverriding = Child methodOverriding
c.methodOverriding = Child methodOverriding

4. Static Method
p.staticMethod = Parent Static Method
c.staticMethod = Child Static Method

1. 변수

- 참조변수 타입을 따라간다. (Parent 참조타입의 경우 parent의 name, Child 참조타입의 경우 child의 name)

 

2. 메서드 (오버라이딩 X)

- 참조변수에 관계없이 Parent에서 정의된 메서드가 호출된다.

- Child에서 해당 메서드를 오버라이딩 하지 않았으므로, 선택의 여지없이 유일하게 정의된 Parent의 메서드가 호출된다.

 

3. 메서드 (오버라이딩 O)

- 참조변수에 관계없이 인스턴스 타입에서 오버라이딩 된 메서드가 호출된다.

- 오버라이딩을 활용한 다형성에서 주로 활용되는 중요한 성질이다.

 

4. 정적 메서드

- 참조변수 타입을 따라간다.

- 정적 메서드의 경우, 오버라이딩의 개념이 아닌 각 클래스에서 정의된 클래스 메서드이므로 참조변수의 타입에 대한 정적 메서드를 호출한다.

 

3. 정리 

- 다형성을 활용할 때 가장 자주 사용되는 오버라이딩에 대해서만 참조변수에 관계없이 인스턴스 타입에 해당하는 메서드가 호출된다.

- 그 외의 참조 (변수, 정적 메서드, 오버라이딩 되지 않은 메서드)에 대해서는 참조변수 타입을 따라감에 주의하자.


Reference

자바의 정석 1권 - 5.4 참조변수와 인스턴스의 연결