다운캐스팅은 잘못하면 심각한 런타임 오류가 발생할 수 있다.
package poly.basic;
// 다운캐스팅을 자동으로 하지 않는 이유
public class CastingMain4 {
public static void main(String[] args) {
Parent parent1 = new Child();
Child child1 = (Child) parent1;
child1.childMethod(); // 문제 없음
Parent parent2 = new Parent();
Child child2 = (Child) parent2; // 런타임 오류 - ClassCastException
child2.childMethod(); // 실행 불가
}
}
child1.childMethod()
는 잘 호출되었지만, child2.childMethod()
는 실행되지 못하고, 그 전에 오류가 발생했다.
parent1
의 경우 다운캐스팅을 해도 문제가 되지 않는다.
parent2
를 다운캐스팅하면 ClassCastException
이라는 런타임 오류가 발생한다.
이 코드를 자세히 알아보자.
Parent parent2 = new Parent();
먼저 new Parent()
로 부모 타입으로 객체를 생성한다. 따라서 메모리 상에 자식 타입은 전혀 존재하지 않는다. 생성 결과를 parent2
에 담아둔다. 이 경우 같은 타입이므로 여기서는 문제가 발생하지 않는다.
Child child2 = (Child) parent2;
parent2
를 Child
타입으로 다운캐스팅한다. 그런데 parent2
는 Parent
로 생성이 되었다. 따라서 메모리 상에 Child
자체가 존재하지 않는다. Child
자체를 사용할 수 없는 것이다.
자바에서는 이렇게 사용할 수 없는 타입으로 다운캐스팅하는 경우에 ClassCastException
이라는 예외를 발생시킨다. 예외가 발생하면 다음 동작이 실행되지 않고, 프로그램이 종료된다. 따라서 child2.childMethod()
코드 자체가 실행되지 않는다.
업캐스팅의 경우 이런 문제가 절대로 발생하지 않는다. 왜냐하면 객체를 생성하면 해당 타입의 상위 부모 타입은 모두 함께 생성된다! 따라서 위로만 타입을 변경하는 업캐스팅은 메모리 상에 인스턴스가 모두 존재하기 때문에 항상 안전하다. 따라서 캐스팅을 생략할 수 있다.
반면에 다운캐스팅의 경우 인스턴스에 존재하지 않는 하위 타입으로 캐스팅하는 문제가 발생할 수 있다. 왜냐하면 객체를 생성하면 부모 타입은 모두 함께 생성되지만 자식 타입은 생성되지 않는다. 따라서 개발자가 이런 문제를 인지하고 사용해야 한다는 의미로 명시적으로 캐스팅을 해주어야 한다.
클래스 A, B, C는 상속 관계다.
new C()
로 인스턴스를 생성하면 인스턴스 내부에 자신과 부모인 A, B, C가 모두 생성된다. 따라서 C의 부모 타입인 A, B, C 모두 C 인스턴스를 참조할 수 있다. 상위로 올라가는 업캐스팅은 인스턴스 내부에 부모가 모두 생성되기 때문에 문제가 발생하지 않는다.
A a = new C()
: A로 업캐스팅B b = new C()
: B로 업캐스팅C c = new C()
: 자신과 같은 타입new B()
로 인스턴스를 생성하면 인스턴스 내부에 자신과 부모인 A, B가 생성된다. 따라서 B의 부모 타입인 A, B 모두 B 인스턴스를 참조할 수 있다. 상위로 올라가는 업캐스팅은 인스턴스 내부에 부모가 모두 생성되기 때문에 문제가 발생하지 않는다. 하지만 객체를 생성할 때 하위 자식은 생성되지 않기 때문에 하위로 내려가는 다운캐스팅은 인스턴스 내부에 없는 부분을 선택하는 문제가 발생할 수 있다.
A a = new B()
: A로 업캐스팅B b = new B()
: 자신과 같은 타입C c = new B()
: 하위 타입은 대입할 수 없음, 컴파일 오류C c = (C) new B()
: 하위 타입으로 강제 다운캐스팅, 하지만 B 인스턴스에 C와 관련된 부분이 없으므로 잘못된 캐스팅, ClassCastException
런타임 오류 발생컴파일 오류는 변수명 오타, 잘못된 클래스 이름 사용 등 자바 프로그램을 실행하기 전에 발생하는 오류이다. 이런 오류는 IDE에서 즉시 확인할 수 있기 때문에 안전하고 좋은 오류이다.
런타임 오류는 이름 그대로 프로그램이 실행되고 있는 시점에 발생하는 오류이다. 런타임 오류는 매우 안좋은 오류이다. 왜냐하면 보통 고객이 해당 프로그램을 실행하는 도중에 발생하기 때문이다.
출처 : 김영한의 실전 자바 - 기본편
https://www.inflearn.com/course/김영한의-실전-자바-기본편/dashboard