Type Casting in Java — Widening vs Narrowing, ClassCastException
Fast recall
Quick revision
Core answer
int → long → float → double, implicit, safe. Narrowing primitive: explicit (int), truncates. Upcasting (reference): child → parent, implicit, always safe. Downcasting: parent → child, explicit (Dog), throws ClassCastException if actual type doesn't match — always instanceof first. Pattern matching (Java 16+): if (obj instanceof Dog dog) { dog.bark(); } — combines check and cast safely.Whether the candidate understands the difference between safe widening conversions (automatic) and risky narrowing conversions (require explicit cast), and can explain ClassCastException in object hierarchies vs data loss in primitive narrowing
Assuming a cast changes the object itself — casting only changes the reference type, not the underlying object. Confusing primitive narrowing (data loss, silent truncation) with reference narrowing (ClassCastException at runtime). Not using instanceof before downcasting
Mention Java 16+ pattern matching with instanceof — `if (obj instanceof String s)` eliminates the separate cast. Explain that widening primitives can lose precision: long → float and int → float lose significant digits because float has only 24 bits of mantissa
Interview-ready guide
Interview answer
Java has two casting contexts — primitives and references — and they fail in completely different ways.
Primitive casting
- Widening (
int → long → double) is implicit and safe - Narrowing (
long → int) requires an explicit cast and silently truncates:(int) 3_000_000_000Lbecomes a negative number with no exception - Hidden precision trap:
int → floatis technically widening, butfloathas only 24 bits of mantissa;16_777_217becomes16_777_216.0fsilently
Reference casting
- Upcasting (child → parent) is implicit and always safe — you just lose access to child-specific methods
- Downcasting (parent → child) requires explicit cast and throws
ClassCastExceptionat runtime if the object isn't actually that type - Critical insight: casting never changes the object in memory — it only changes how the compiler views the reference
Modern safety — pattern matching (Java 16+)
if (obj instanceof String s)combines type check and variable binding in one step- Eliminates the old check-then-cast antipattern where the instanceof and the cast can drift apart
I recommend always using instanceof pattern matching before downcasting — it checks and binds in one expression, eliminating the common two-step mistake.
Type Casting in Java — Widening vs Narrowing, ClassCastException
Direct Answer
Widening primitive: int → long → float → double, implicit, safe. Narrowing primitive: explicit (int), truncates. Upcasting (reference): child → parent, implicit, always safe. Downcasting: parent → child, explicit (Dog), throws ClassCastException if actual type doesn't match — always instanceof first. Pattern matching (Java 16+): if (obj instanceof Dog dog) { dog.bark(); } — combines check and cast safely.
Common Mistakes & Pitfalls
Assuming a cast changes the object itself — casting only changes the reference type, not the underlying object. Confusing primitive narrowing (data loss, silent truncation) with reference narrowing (ClassCastException at runtime). Not using instanceof before downcasting
Check your understanding
Answer these without looking back at the article.
- What is the difference between a compile-time error and a ClassCastException for invalid casts?
- Why should you always check instanceof before downcasting a reference?
- What is Java 16 pattern matching for instanceof and how does it eliminate the redundant cast?
- What data is actually lost when you narrow cast from double to int?
- Can you cast between two completely unrelated classes — what happens at compile time vs at runtime?
Related interview prep categories
1Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.