Your class hierarchy looks like this:

Object x
can be casted to class Y
, if runtime type of x
is subclass of Y
. Or, in other words, if there is a path from runtime type of x
to Y
. By "runtime type" i mean the type of object (the one used when constructing object) as opposed to type of variable (the one from variable declaration).
This is valid:
b = new B();
(B)(I)b;
Object stored in b
has type B
. It's casted to I
and then back to B
. B
is a subclass of both of them. Cast to I
doesn't actually do anything and is meant only to confuse you.
However, neither of those is valid:
a = new A();
(B)(I)a;
(B)a;
They will both fail with exception: java.lang.ClassCastException: A cannot be cast to B
. a
has type A
which is not a subclass of B
. There is a relation between A
and B
, but it's in the opposite direction - B
is a subclass of A
.
For more detailed explanation see here: http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html