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