Hi Mr. Tyler,
Why is this line valid in the code :
A a2=(A)m;
There is no relationship between A and m.
Please help explain.
Thanks,
Shachi
It's true that class A and interface M has no relationship, but you are allowed to cast between A and M at the compile time.
The simplest answer to why would be about the compiler which only deals with reference types, not with objects. With that constraint, compiler has to speculate all possible happenings of the objects at the runtime. Let's keep that aside for now.
Another thing you should know the compiler knows all possible SUPERtypes of any given type. Consider this one:
interface X { } class Y implements X { } class Z extends Y { }
Now, looking at class Z, we (and the compiler) can identify all SUPERtypes of Z, right? Namely, they are Y, and X. However, can we speculate the SUBtypes of Z? No! because that is a future thing. Suppose we have compiled the above class set as-is and packaged the whole thing into a JAR file. Now you share this JAR file on internet so everyone can download it for free. They can download your JAR and extend class Z from another class without affecting your compiled code, right? That is why we say SUBtypes are future things. At the compile time, you can't decide what are the SUBclasses there will be (unless the class is final, at which point no one will be able to extend it). Because of this reason, the compiler doesn't even look at the available SUBclasses.
Now, getting back to your question, the compiler knows the all SUPERtypes of A (which is only java.lang.Object). However, it doesn't know about the SUBtypes there will be. Suppose someone will someday write a class named "Future", which extends A and implements M:
class Future extends A implements M { }
In this case, following statements will be valid at both compile-time and runtime:
A a = new Future(); M i = (M)a;
Got it? In the second line, you can see that we have casted the reference type from A to M, which is now a valid cast.
If I describe this whole thing with simple words, there is a possibility that a reference with type A may contain an object that is assignable to a reference type M. For this reason, it lets us use instanceof operator between A and M.
Got it?
Here is a cool thing to try: make the class A final and then try to compile it. The compiler now knows there will NOT be any subtype of A. Can you guess the result now?