java.lang.ClassCastException은 Java에서 대표적인 비검사형(unchecked) 예외 중 하나입니다. 프로그램 실행 중 한 클래스 타입의 객체를 서로 다른 클래스 타입으로 강제 형변환(casting)하려고 시도할 때 발생합니다. 컴파일 시점에는 오류가 감지되지 않고, 런타임에 예외가 던져지기 때문에 주의가 필요합니다.
ClassCastException이 발생하는 경우
- 부모 클래스 객체를 자식 클래스 타입으로 캐스팅하려고 할 때 발생합니다. 실제 객체가 부모 클래스 인스턴스라면 자식 타입으로 변환하는 것은 허용되지 않습니다.
- 상속 관계가 전혀 없는 두 클래스 사이에서 객체를 캐스팅하려고 할 때도 발생합니다. 두 클래스 간에 아무런 계층 관계(상속 또는 구현)가 없다면 형변환이 불가능합니다.
예제 코드
아래 예제는 부모-자식 상속 관계에서 ClassCastException이 어떻게 발생하는지 보여줍니다.
class ParentTest {
String parentName;
ParentTest(String n1){
parentName = n1;
}
public void display() {
System.out.println(parentName);
}
}
class ChildTest extends ParentTest {
String childName;
ChildTest(String n2) {
super(n2);
childName = n2;
}
public void display() {
System.out.println(childName);
}
}
public class Test {
public static void main(String args[]) {
ChildTest ct1 = new ChildTest("Jai");
ParentTest pt1 = new ParentTest("Adithya");
pt1 = ct1; // 업캐스팅: 항상 안전함
pt1.display();
ParentTest pt2 = new ParentTest("Sai");
ChildTest ct2 = (ChildTest)pt2; // 다운캐스팅 시도 → 예외 발생
}
}
실행 결과
Jai
Exception in thread "main" java.lang.ClassCastException: ParentTest cannot be cast to ChildTest
at Test.main(Test.java:30)
결과 분석
첫 번째 출력인 Jai는 자식 객체를 부모 타입 변수에 할당한 업캐스팅(upcasting) 사례로, 아무 문제 없이 정상 동작합니다. 반면 두 번째 코드에서는 실제로 ParentTest 인스턴스인 pt2를 자식 타입인 ChildTest로 강제 캐스팅하려 했기 때문에 런타임에 ClassCastException이 발생했습니다.
예외를 피하는 방법
다운캐스팅을 수행하기 전에는 반드시 instanceof 연산자로 객체의 실제 타입을 확인하는 것이 좋습니다.
if (pt2 instanceof ChildTest) {
ChildTest ct2 = (ChildTest) pt2;
}
이처럼 instanceof 검사를 활용하면 런타임 예외를 사전에 방지하고, 더 안전하고 견고한 Java 코드를 작성할 수 있습니다.