Card 06/ 09

GotchaDifficulty: Advanced1 min

Why Your Cast Compiled and Then Threw

A loop that handles a mixed list works for weeks and then throws on one record. The line it throws on has no method call in it.

java
for (Shape s : shapes) {
    Circle c = (Circle) s;
    System.out.println(c.radius());
}
text
Exception in thread "main" java.lang.ClassCastException: class Square cannot be cast to class Circle (Square and Circle are in unnamed module of loader 'app')

A cast is not a conversion. It is you telling the compiler "trust me, this is a Circle", and the compiler accepting it because a Circle could be a Shape. Nothing is checked until the line runs, and then the virtual machine checks it properly and throws when you were wrong.

instanceof is the check the cast skips. Since Java 16 it can bind the narrowed variable in the same expression, which removes the cast entirely.

java
for (Shape s : shapes) {
    if (s instanceof Circle c) {
        System.out.println(c.radius());
    }
}

Before reaching for either, ask whether Shape could declare the method. If every shape can answer it, the cast goes away and the loop goes back to naming no types at all.