본문 바로가기

프로그래밍언어/Java

[Java 기본] 다형성과 캐스팅

다형성과 캐스팅


Parent poly = new Child() 와 같이 부모 타입의 변수를 사용하게 되면 poly.childMethod() 와 같이 자식 타입에 있는 기능은 호출할 수 없다.

 

    public static void main(String[] args) {
        // 부모 변수가 자식 인스턴스 참조( 다형적 참조)
        Parent poly = new Child();
        // 단 자식의 기능은 호출할 수 없다. 
        // poly.childMethod();
        
        // 다운 캐스팅(부모 타입 -> 자식 타입)
        Child child = (Child) poly;
        child.childMethod();
        
    }

 

=> poly.childMethod()를 호출하면 먼저 참조값을 사용해서 인스턴스를 찾는다.  

poly는 Parent 타입이므로 Parent를 찾지만 parentMethod() 밖에 없다. 부모에서 자식 메서드를 찾으러 내려가진 않는다. 

따라서 컴파일 오류가 발생한다. 

 

다운캐스팅


이럴 때는 호출하는 타입을 자식 타입인 Child 타입으로 변경하면 childMethod()를 호출할 수 있다. 

Child child = poly

=> 자식은 부모를 담을 수 없기 때문에 오류가 발생한다. 

 

이럴 때는 다운캐스팅을 사용해서 부모 타입을 자식 타입으로 변경해야 한다. 

Child child = (Child) poly

=> 이렇게 특정 타입으로 변경하는 것을 캐스팅이라 한다. 

캐스팅을 한다고 해서 Parent poly 의 타입이 변하는 것은 아니다. 해당 참조값을 꺼내고 꺼낸 참조값이 Child 타입이 되는 것이다. 

 

  • c업캐스팅(upcasting): 부모 타입으로 변경
  • 다운캐스팅(downcasting): 자식 타입으로 변경

 

캐스팅의 종류


1. 일시적 다운캐스팅

       // 일시적 다운캐스팅 - 해당 메서드를 호출하는 순간만 다운캐스팅
        ((Child) poly).childMethod();

 

2. 업캐스팅

자식 타입을 부모 타입으로 변경하는 것을 업캐스팅이라 한다. 

        Child child = new Child();
        Parent parnet1 = child; // 업캐스팅은 생략 가능.

=> 업캐스팅은 생략할 수 있다. 

 

다운캐스팅과 주의점


다운캐스팅은 잘못하면 심각한 런타임 오류가 발생할 수 있다. 

    // 다운캐스팅을 자동으로 하지 않는 이유
    public static void main(String[] args) {
        Parent parent1 = new Child();
        Child child1 = (Child)parent1;
        child1.childMethod(); // 문제 없음

        Parent parent2 = new Parent();
        Child child2 = (Child)parent2; // 런타임 오류
        child2.childMethod(); // 실행불가
    }

 

실행결과

=> ClassCastException 이 발생한다. 

 

parent2는 Parent로 객체를 생성한다. 따라서 메모리 상에 자식 타입은 존재하지 않는다. 

여기서 parent2를 Child 타입으로 다운캐스팅한다. parent2 는 Parent로 생성되었기 때문에 메모리에 Child 자체가 존재하지 않는다. Child 자체를 사용할 수 없는 것이다. 

자바에서는 이렇게 사용할 수 없는 타입으로 캐스팅하는 경우에 ClassCastException 이라는 예외를 발생시킨다. 

 

업캐스팅의 경우 이런 문제가 발생하지 않는다. 왜냐하면 객체를 생성하면 해당 타입의 상위 부모타입은 모두 함께 생성되기 때문이다. 따라서 위로만 타입을 변경하는 업캐스팅은 메모리 상에 인스턴스가 모두 존재하기 때문에 안전하다. 따라서 캐스팅을 생략할 수 있다.

반면 다운캐스팅의 경우 인스턴스에 존재하지 않는 하위 타입으로 캐스팅하는 문제가 발생할 수 있다. 왜냐하면 객체를 생성하면 부모 타입은 생성되지만 자식 타입은 생성되지 않기 때문이다. 따라서 개발자가 명시적으로 캐스팅을 해주어야 한다. 

 

 

 

* 인프런 '김영한의 실전 자바 - 기본편'을 참고하여 작성하였습니다.