06 April 2012

Casting and instanceof clause in Java

In java, an instance of a class can be cast to parent class references implicitly (a.k.a. upcasting). Casting to subclass references must be explicitly declared (a.k.a. downcasting). Downcasting is safe when an instanceof control of the reference and target class type is implemented before casting.

There are some reasonable restriction rules that lead developers to write sensible code while using instanceof clause in java.
  1. A class reference can only be checked against parent classes, sub-classes or own class.
  2. A class reference can be checked against any interface.
  3. An interface reference can be checked against any class.
Other cases, out of scope of these rules will cause compilation error. The reason of first rule is preventing developer from coding any impossible instanceof compares with comparing an instance of a class with any unrelated types in O-O hierarchy tree. The second and third rules are the result of possibility that a class can extend one class but implements many interfaces. For example, a sub-class extends the reference type but also implements another interface. It is impossible to know with only analyzing reference type.

public class TestIt {

static class A { }
static class B extends A implements C{ }
interface C {}
static class D {}
public static void main(String[] args) {
  // first an instance of B is created
  // then reference of A is pointing new instance of B
  // java does not force developer to declare explicit casting
  // A a = (A) new B(); // also legal but not required  
  A a = new B(); 
  // safe downcasting should be implemented like this:
  // checking the object referenced by reference 'a' is
  // instance of B. RULE1
  if(a instanceof B) {
    // if true than downcasting is safe
    // otherwise at runtime; java.lang.ClassCastException MAY occur
    B b = (B) a;

  // any class reference can be controlled(instanceof) with any interface
  // casting must be explicitly declared RULE2
  if(a instanceof C) {
    C c = (C) a;
    // any interface reference can be controlled(instanceof) with any class 
    // casting must be explicitly declared RULE3
    if(c instanceof A) {
       A a2 = (A) c;
  // nonsense check with any unrelated classes; causes compiler error RULE1
  if(a instanceof D) {
    D d = (D) a;

  // it will always produce false;
  // but no warning or error by compiler produced becauseof RULE1
  if(new A() instanceof B) {
   B b = (B) new A(); // even no compiler error, runtimeexception will occur