I am not sure I understand code on line 1 below?
interface Talkable{ }
class Device{}
class Phone extends Device implements Talkable{}
Talkable d = (Talkable) new Device(); //line 1
Talkable p = new Phone(); //line 2
I understand line2 since Phone implements Talkable, but Device and Talkable are unrelated, How can line1 be legal?
The reason the compiler accepts this is explained in the JLS section 5.5.1 (relevant part in bold):
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 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 (§4.5), 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 (§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).
In your case, a java.lang.ClassCastException
will be thrown at runtime since Device
cannot be converted to Talkable
. But until the program executes, the compiler allows the cast because there may be a subclass of Device
that implements Talkable
.
Actually, in Java it is perfectly valid to cast one related type to another (even if the casting makes little sense). You will get an error during runtime if the types are not compatible.
For example :
public static void main(String[] args) {
String s = (String) new Object();
System.out.println(s.intern());
}
Compiles fine but gives Exception in thread "main" java.lang.ClassCastException: java.lang.Object cannot be cast to java.lang.String
at Sample.main(Sample.java:5)
during runtime
Line 1 will throw a runtime exception. The compiler does not check at compile time if the cast can succesfully be done. This is why it is sometimes advisable to check this first with the instanceof
operator.
In general, you can always cast a variable x
of type A
to any interface C
, because there may exist a class B extends A implements C
, or a class B implements A, C
The same is not true for casting a variable x
of class A
to any class D
, because there cannot exist a subclass E extends A, D
, because a class may not extend multiple classes.
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