ClassCastException in Java
Fast recall
Quick revision
Core answer
Understanding of Java's type system, runtime type checking, and the difference between compile-time and runtime types
Blindly casting without instanceof check when dealing with Object or inheritance hierarchies
Mention that generics prevent ClassCastException at compile time, and Java 16 pattern matching for instanceof eliminates the redundant cast
Interview-ready guide
Interview answer
ClassCastException happens when you try to cast an object to a type that it's not actually an instance of.
Java has compile-time types and runtime types. The compiler checks if a cast is theoretically possible based on variable declarations, but at runtime the JVM checks the actual object type. If they don't match, you get ClassCastException.
For example, if you store a String in an Object variable and then try to cast that Object to Integer, the compiler allows it because both String and Integer extend Object. But at runtime, the actual object is a String, not an Integer, so the cast fails and throws the exception. To prevent it, you use instanceof to check the type before casting.
The old way was to do instanceof check, then cast on the next line. Java 16 introduced pattern matching where you can do both in one line — if payment instanceof CreditCardPayment cc — and now cc is already cast and ready to use inside the if block. The better solution is to avoid casting altogether by using generics.
If your method accepts a generic type parameter like less than T extends Payment greater than, the compiler enforces type safety and you never need to cast. That catches errors at compile time instead of runtime. Another common mistake is using raw types like List without generics.
Then you have to cast every element you pull out, which risks ClassCastException. Use List less than String greater than and the compiler knows the type, so no casting is needed.
ClassCastException in Java
Direct Answer
ClassCastException is thrown when you attempt to cast an object to a class or interface that it's not an instance of. This happens at runtime when the actual type of the object is incompatible with the target type you're casting to. Prevention includes using instanceof checks before casting and leveraging generics for compile-time type safety.
Code Example
public class PaymentProcessor {
public void processPayment(Object payment) {
// WRONG: blind casting without type check
// CreditCardPayment cc = (CreditCardPayment) payment; // throws if payment is not CreditCardPayment
// OLD WAY: instanceof check then cast
if (payment instanceof CreditCardPayment) {
CreditCardPayment cc = (CreditCardPayment) payment;
System.out.println("Processing card: " + cc.getCardNumber());
}
// JAVA 16+: pattern matching eliminates redundant cast
if (payment instanceof CreditCardPayment cc) {
System.out.println("Processing card: " + cc.getCardNumber());
} else if (payment instanceof BankTransfer bt) {
System.out.println("Processing transfer: " + bt.getAccountNumber());
}
}
// BEST: use generics to prevent ClassCastException at compile time
public <T extends Payment> void processTypedPayment(T payment) {
payment.process(); // no cast needed, type is known
}
public void demonstrateProblem(List rawList) {
rawList.add("text");
rawList.add(123);
// Integer num = (Integer) rawList.get(0); // throws ClassCastException at runtime
}
}
Common Mistakes & Pitfalls
- Casting without instanceof check: Freshers see a compiler warning about unchecked cast and ignore it, then blindly cast Object to a specific type assuming it'll work. At runtime, if the object is a different type, ClassCastException crashes the program. Always check with instanceof first unless you're absolutely certain of the type.
- Using raw types instead of generics: Writing List without the generic type less than T greater than forces you to cast every element you retrieve, opening the door to ClassCastException. Use List less than String greater than so the compiler knows the element type and no casting is needed.
- Confusing compile-time and runtime types: Declaring Object obj equals new String and then casting obj to Integer compiles fine because the compiler only sees Object, but at runtime it fails because the actual object is a String, not an Integer.
Check your understanding
Answer these without looking back at the article.
- How do generics prevent ClassCastException?
- What is the pattern matching for instanceof in Java 16?
- What is heap pollution and how does it relate to ClassCastException?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.