[인프런 Java] 다운캐스팅과 주의점

코드 속의 "진돌"·2024년 3월 19일
0
post-thumbnail

✅ 다운캐스팅과 주의점


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

✏️ CastingMain4

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;

parent2Child 타입으로 다운캐스팅한다. 그런데 parent2Parent로 생성이 되었다. 따라서 메모리 상에 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 런타임 오류 발생



📚 컴파일 오류 vs 런타임 오류

컴파일 오류는 변수명 오타, 잘못된 클래스 이름 사용 등 자바 프로그램을 실행하기 전에 발생하는 오류이다. 이런 오류는 IDE에서 즉시 확인할 수 있기 때문에 안전하고 좋은 오류이다.

런타임 오류는 이름 그대로 프로그램이 실행되고 있는 시점에 발생하는 오류이다. 런타임 오류는 매우 안좋은 오류이다. 왜냐하면 보통 고객이 해당 프로그램을 실행하는 도중에 발생하기 때문이다.


출처 : 김영한의 실전 자바 - 기본편
https://www.inflearn.com/course/김영한의-실전-자바-기본편/dashboard

profile
매일 성장하는 주니어 개발자의 기록📝

0개의 댓글