1. ❓ ClassCastException이란 무엇인가요?
ClassCastException은 서로 상속 관계가 아니거나, 실제 객체의 타입과 일치하지 않는 타입으로 형변환(Casting)을 시도할 때 발생하는 언체크드 예외(Unchecked Exception)입니다.
자바는 컴파일 시점에 어느 정도 타입 체크를 해주지만, 부모 타입으로 선언된 변수를 자식 타입으로 강제 변환할 때는 실행 시점(Runtime)에 실제 객체가 무엇인지 확인합니다. 이때 변환이 불가능하면 JVM이 이 예외를 던집니다.
2. 🔍 왜 발생하나요? (주요 실수 사례)
✅ 1. 부모 객체를 자식 타입으로 변환할 때
부모 클래스로 생성된 객체는 자식 클래스의 정보를 가지고 있지 않습니다. 이를 억지로 자식 타입에 담으려 하면 에러가 발생합니다.
Animal animal = new Animal(); // 부모 객체 생성
Dog dog = (Dog) animal; // 에러! 실제 객체는 Dog가 아님
✅ 2. 형제 클래스 간의 변환
같은 부모를 가졌더라도 자식 클래스끼리는 서로 변환할 수 없습니다.
Animal cat = new Cat();
Dog dog = (Dog) cat; // 에러! 고양이는 개가 될 수 없음
✅ 3. 제네릭(Generic) 도입 이전의 컬렉션 사용
과거 ArrayList 등에 타입을 지정하지 않고 사용한 뒤, 꺼낼 때 잘못된 타입으로 변환하면 발생합니다. (최근에는 제네릭 덕분에 컴파일 시점에 예방되는 경우가 많습니다.)
3. 🛡️ 예외를 방지하는 실전 팁
1️⃣ instanceof 연산자로 미리 확인하기
형변환을 하기 전, 실제 객체가 해당 타입이 맞는지 검사하는 가장 안전한 방법입니다.
if (animal instanceof Dog) {
Dog dog = (Dog) animal;
dog.bark();
}
2️⃣ Pattern Matching for instanceof (Java 14+)
최신 자바에서는 체크와 변환을 한 번에 처리하여 코드를 더 깔끔하게 만들 수 있습니다.
if (animal instanceof Dog dog) {
dog.bark(); // 별도의 캐스팅 코드 없이 바로 dog 변수 사용 가능
}
3️⃣ 제네릭(Generics) 적극 활용
컴파일 시점에 타입을 체크하도록 설계하여 런타임에 발생할 ClassCastException을 사전에 차단하세요.
💡 시니어의 조언: '다형성'을 오해하지 마세요
ClassCastException이 자주 발생한다는 것은 프로그램 설계가 객체지향 원칙에서 조금 벗어나 있다는 신호일 수 있습니다. 자식 클래스의 특정 메서드를 쓰기 위해 계속해서 다운캐스팅(Downcasting)을 하고 있다면, 차라리 부모 클래스에 추상 메서드를 선언하고 자식들이 각자 구현하게 하는 **다형성(Polymorphism)**을 활용하는 것이 더 바람직합니다.
"이 객체가 무엇인지 묻지 말고, 그냥 시키세요(Tell, Don't Ask)." 이것이 이 예외를 만나는 횟수를 줄이는 최고의 설계 비결입니다.
'개발 > Trouble Shooting' 카테고리의 다른 글
| ORA-01017: invalid username/password; logon denied (0) | 2025.12.29 |
|---|---|
| 잘못된 인자 전달 금지: IllegalArgumentException 완벽 가이드 (0) | 2025.12.29 |
| 0으로 나눌 수 없습니다! ArithmeticException 완벽 가이드 (0) | 2025.12.29 |
| 정해진 선을 넘지 마세요: ArrayIndexOutOfBoundsException 완벽 가이드 (0) | 2025.12.29 |
| 자바의 영원한 숙제: NullPointerException (NPE) 완벽 가이드 (0) | 2025.12.29 |