Card 06/ 09
ClassCastException: A Cast That Compiled and Then Threw
A loop over a mixed list works for weeks, then throws on a line with no method call in it.
A cast, such as (Circle) s, tells the compiler to treat a reference as a narrower type. The compiler accepts it if the object could be that type, and the JVM checks it when the line runs, throwing ClassCastException if the object is not. instanceof is the check to make first.
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:
for (Shape s : shapes) {
Circle c = (Circle) s;
System.out.println(c.radius());
}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 Shape could be a Circle. 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.
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.
← → move through sections and cards