Why cast after an instanceOf?

Old code will not work correctly

The implied cast feature is justified after all but we have trouble to implement this FR to java because of backward-compatibility.

See this:

public class A {
    public static void draw(Square s){...} // with implied cast
    public static void draw(Object o){...} // without implied cast
    public static void main(String[] args) {
        final Object foo = new Square();
        if (foo instanceof Square) {
            draw(foo);
        }
    }
}

The current JDK would compile the usage of the second declared method. If we implement this FR in java, it would compile to use the first method!

🔴 JDK 14

We finally implemented this feature in JDK 14. As you might have noticed you can declare a new variable within the instanceof-linkage. This new variable has been defined by the value of a automatically downcast to the specified type.

if (any instanceof String s) {
  System.out.println(s);
}

The compiler does not infer that since you are in the block, you have done a successful check for the type of the object. An explicit cast is still required to tell the compiler that you wish to reference the object as a different type.

if (p1 instanceof Square) {
    // if we are in here, we (programmer) know it's an instance of Square
    // Here, we explicitly tell the compiler that p1 is a Square
    c1 = (Square) p1;
}

In C# you can do the check and the cast in 1 call:

c1 = p1 as Square;

This will cast p1 to a Square, and if the cast fails, c1 will be set to null.


Keep in mind, you could always assign an instance of Square to a type higher up the inheritance chain. You may then want to cast the less specific type to the more specific type, in which case you need to be sure that your cast is valid:

Object p1 = new Square();
Square c1;

if(p1 instanceof Square)
    c1 = (Square) p1;