Tuesday, 18 September 2012

Puzzle 50: Not Your Type


This puzzle tests your understanding of Java's two classiest operators: instanceof and cast. What does each of the following three programs do?
public class Type1 {

    public static void main(String[] args) {

        String s = null;

        System.out.println(s instanceof String);

    }

}



public class Type2 {

    public static void main(String[] args) {

        System.out.println(new Type2() instanceof String);

    }

}



public class Type3 {

    public static void main(String args[]) {

        Type3 t3 = (Type3) new Object();

    }

}


Solution 50: Not Your Type

The first program, Type1, illustrates the behavior of the instanceof operator when applied to a null object reference. Although null is a subtype of every reference type, the instanceof operator is defined to return false when its left operand is null. Therefore, Type1 prints false. This turns out be the most useful behavior in practice. If instanceof tells you that an object reference is an instance of a particular type, you are assured that you can cast it to that type and invoke methods of the type without fear of a ClassCastException or a NullPointerException.
The second program, Type2, illustrates the behavior of the instanceof operator when testing an instance of one class to see whether it is an instance of an unrelated class. You might expect this program to print false. After all, an instance of Type2 isn't an instance of String, so the test should fail, right? No. The instanceof test fails at compile time with an error message like this:
Type2.java: inconvertible types

found: Type2, required: java.lang.String

        System.out.println(new Type2() instanceof String);

                           ^


The program fails to compile because the instanceof operator requires that if both operands are class types, one must be a subtype of the other [JLS 15.20.2, 15.16, 5.5]. Neither Type2 nor String is a subtype of the other, so the instanceof test results in a compile-time error. This error helps alert you to instanceof tests that probably don't do what you want.
The third program, Type3, illustrates the behavior of the cast operator when the static type of the expression to be cast is a superclass of the cast type. Like the instanceof operation, if both types in a cast operation are class types, one must be a subtype of the other. Although it is obvious to us that this cast will fail, the type system is not powerful enough to know that the run-time type of the expression new Object() cannot be a subtype of Type3. Therefore, the program throws a ClassCastException at run time. This is a bit counterintuitive: The second program makes perfect sense but doesn't compile; this one makes no sense but does.
In summary, the first program illustrates a useful corner case in the run-time behavior of instanceof. The second program illustrates a useful corner case in its compile-time behavior. The third program illustrates a corner case in the behavior of the cast operator where the compiler fails to save you from your folly, and the VM is left to take up the slack at run time.

    No comments:

    Post a Comment

    Your comments are welcome!