Why can any non-final class be casted to an interface?
A cast to an interface is always allowed at compile-time unless the class
is final class and does not implement this interface.
5.5
Casting Conversion in JLS, you are trying to cast a reference type S to
a reference type T:
-
If S is a class type:
-
If T is a class type, then either |S| <: |T|, or |T| <: |S|; otherwise a
compile-time error occurs. Furthermore, if there exists a supertype X of T, and
a supertype Y of S, such that both X and Y are provably distinct parameterized
types, and that the erasures of X and Y are the same, a compile-time error
occurs.
-
If T is an interface type:
-
If S is not a final class, then, if there exists a supertype X of T, and a
supertype Y of S, such that both X and Y are provably distinct parameterized
types, and that the erasures of X and Y are the same, a compile-time error
occurs. Otherwise, the cast is always legal at compile time (because even if S
does not implement T, a subclass of S might).
-
If S is a final class, then S must implement T, or a compile-time error occurs.
-
If T is a type variable, then this algorithm is applied recursively, using the
upper bound of T in place of T.
-
If T is an array type, then S must be the class Object, or a compile-time error
occurs.
The idea is that even if
the class does not implement the interface, but one of its subclass maght. If the actually object class does not implement the
interface then you will get a ClassCastException error at runtime.
For example,
interface MyInterface{}
class MyObject{}
public class Program {
public static void main(String arg[]){
Program po = new Program();
MyInterface it = (MyInterface)po; //compile fine
MyObject obj = (MyObject)po; //compile time error
}
}
Why not final class? The compiler knows at compile time exactly what interfaces
are implemented by the final class.
If the compiler can determine at compile time that the final class can never be instanceof the interface, that's a compile time error.