<code>ClassCastException</code> in Java
ClassCastException is thrown when you cast an object to a type it doesn't actually implement or extend. It's an unchecked exception β always a bug, caused by a mismatch between what the code claims and what the object really is.
The cause
Object o = "hello";
Integer i = (Integer) o; // ClassCastException at runtime
// java.lang.ClassCastException: class java.lang.String
// cannot be cast to class java.lang.Integer
Prevent with instanceof
// Classic
if (o instanceof Integer) {
Integer i = (Integer) o;
...
}
// Pattern matching for instanceof (Java 16+)
if (o instanceof Integer i) {
System.out.println(i + 1); // `i` is in scope and already the right type
}
Pattern matching for switch (Java 21+)
String describe(Object o) {
return switch (o) {
case Integer i -> "int " + i;
case String s -> "string " + s;
case null -> "null";
default -> "other";
};
}
The raw-types trap
// Using raw types bypasses the compile-time check
List list = new ArrayList();
list.add("hi");
list.add(1);
List<String> strings = list; // unchecked warning
String s = strings.get(1); // ClassCastException β runtime
Always use parameterised generics (List<String>), not raw types.
Downcasting collections
Object obj = service.result();
// β Don't blindly cast
List<User> users = (List<User>) obj; // unchecked
// β
Check, then copy (safe but more work)
if (obj instanceof List<?> l) {
List<User> users = new ArrayList<>();
for (Object e : l) if (e instanceof User u) users.add(u);
}
Common mistakes
- Catching
ClassCastExceptionβ never the right fix. Useinstanceof. - Unchecked casts of generics β due to type erasure,
(List<User>) objis a lie to the compiler. Check at runtime. - Casting to a subclass without checking β good code rarely needs downcasts. Reconsider the design if you do.
Related
Pillar: Java exceptions. See also generics and instanceof.