I found following question in my study book and a bit confused:
Given the following code, which option, if used to replace /* INSERT CODE
HERE */, will enable a reference variable of type Roamable to refer to an object of the
Phone class? (Select 1 option.)
interface Roamable{}
class Phone {}
class Tablet extends Phone implements Roamable {
    //INSERT CODE HERE
}
Options are:
Roamable var = new Phone();Roamable var = (Roamable)Phone();Roamable var = (Roamable)new Phone();Roamable and class Phone are unrelated, a reference variable
of type Roamable can’t refer to an object of class Phone.I thought the correct option is 4, however it says it is 3.
But, Phone doesn't implement Roamable interface, so you can't cast, can you?
The correct answer is 3: The compiler sees only that a Phone is being cast to a Roamable and that Phone is not final, so it thinks that the object being cast, although referred to as Phone may be a subclass of Phone that does implement Roamable, so no compile-time error or warning is issued.
According to JLS chapter 5
5.5.1. Reference Type Casting
Given a compile-time reference type S (source) and a compile-time reference type T (target), a casting conversion exists from S to T if no compile-time errors occur due to the following rules. If T is an interface type:
If S is not a final class (§8.1.1), 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 (§8.1.1), then S must implement T, or a compile-time error occurs.
The following code compiles:
interface Roamable{}
class Phone {}
class Tablet extends Phone implements Roamable {
    Roamable var = (Roamable)new Phone(); // Compiles
}
                        Answer would be 4
as
1 is incorrect(explanation --> 4)
2 is incorrect syntax
3 is incorrect typecast.
Note that answer 3 is valid as long as it is just about compilation. When you say you have a instance of Phone class you can type cast into Tablet (Similar to you can cast Object to String). And since Tablet implements Roamable you can very well use a Roamable reference to refer it. Problem will occur at runtime as the Object is really of type Phone. 
This is just one of the linkage patter(in current context) which allows successful compilation. But as Bohemian has mentioned in his answer in general
If we are typecasting a compile time reference S(non final) to compile time reference T then compilation will be successful as
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.
Actually there is no need of Tablet class extending Phone class at all. As long as Phone class is not final compilation will be successful
interface Roamable{}
class Phone {}
class Tablet implements Roamable {
    Roamable var = (Roamable)new Phone(); // Compiles
}
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With