Java — ClassCastException at runtime
Resolve ClassCastException by tracing the actual runtime type and correcting generics or casts.
Symptoms
- java.lang.ClassCastException: class A cannot be cast to class B
- The cast compiles but fails at runtime
- Raw types or unchecked casts hide the mismatch
- Deserialization produces an unexpected type
Possible causes
- An unchecked cast assumes a type the value does not have
- Raw collections or maps hold mixed types
- A generic type parameter is erased so the cast is not verified
- Deserialization into a base type yields a subtype different from the expected one
Diagnosis steps
Read the runtime types in the message
App 2>&1 | grep ClassCastExceptionInterpretation
The message names the actual class and the target class, which reveals where the assumption broke.
Find the unchecked cast
javac -Xlint:unchecked src/*.javaInterpretation
Warning on unchecked casts points to the lines where the compiler cannot guarantee the type.
Log the actual class before casting
System.out.println(value.getClass())Interpretation
Printing the runtime class confirms what the value really is, rather than what the code assumed.
Root cause
A cast assumed a runtime type the value did not have. Type erasure means many casts are unchecked, so the mismatch surfaces only when the code actually runs with that value.
Fix
Correct the generic types so casts are checked, avoid raw collections, verify with instanceof before casting, and align deserialization targets with the actual payload.
Verify the fix
Rerun the failing path and confirm the cast no longer throws, and confirm the value is of the intended type by logging or asserting it.
Symptom walkthrough
A cast compiles but throws ClassCastException when the code runs with certain data. Type erasure makes generic casts unchecked, so the compiler cannot always prevent a mismatch; raw collections and maps make it more likely by allowing mixed element types. The message names both the actual and target classes, which pinpoints the false assumption.
Fix in practice
Use checked generics instead of raw types, guard casts with instanceof where the runtime type varies, and make deserialization targets match the real payload. Prefer polymorphic dispatch over casting so the correct behavior is selected without an explicit cast.
Verification
Rerun the failing path and confirm the cast succeeds, then log or assert the runtime type to be sure the value is what the code now expects. Both the absence of the exception and the correct type matter.
Diagnostic commands
Check the behavior with commands like these:
App 2>&1 | grep ClassCastException
javac -Xlint:unchecked src/*.java
System.out.println(value.getClass())