Java casting in interfaces

Can someone please explain to me how the compiler does not complain about the first casting, but complains about the second?

interface I1 { } interface I2 { } class C1 implements I1 { } class C2 implements I2 { } public class Test{ public static void main(){ C1 o1 = new C1(); C2 o2 = new C2(); Integer o3 = new Integer(4); I2 x = (I2)o1; //compiler does not complain I2 y = (I2)o3; //compiler complains here !! } } 
+69
java casting interface
Apr 24 '13 at 7:54
source share
4 answers

When you press o1 and o3 on (I2) you tell the compiler that the class of the object is actually a subclass of its declared type and that this subclass implements I2 .

The Integer class is final , so o3 cannot be an instance of the Integer subclass: the compiler knows that you are lying. C1 however, is not final, so o1 can be an instance of the subtype C1 , which implements I2 .

If you do C1 final, the compiler will complain too:

 interface I1 { } interface I2 { } final class C1 implements I1 { } class C2 implements I2 { } public class Test{ public static void main(){ C1 o1 = new C1(); C2 o2 = new C2(); Integer o3 = new Integer(4); I2 y = (I2)o3; //compiler complains here !! I2 x = (I2)o1; //compiler complains too } } 
+136
Apr 24 '13 at 8:01
source share

According to JLS chapter 5

5.5.1. Type of reference casting

Given the reference compile-time type S (source) and the compile-time reference type T (target), a cast conversion exists from S to T if compile-time errors do not occur due to the following rules. If T is the type of interface:

If S is not a finite class (ยง8.1.1), then if there is a supertype X of T and a supertype Y of S such that both X and Y are predictable different parameterized types and that the erasures of X and Y are the same, a time error occurs compilation.

Otherwise, listing is always legal at compile time (because even if S does not implement T, there may be a subclass of S).

If S is a finite class (ยง8.1.1), then S must implement T, or a compile-time error occurs.

+32
Apr 24 '13 at 8:06
source share

This is because the Integer class is final, and C1 is not. Thus, an Integer object cannot implement I2, whereas a C1 object can be if it is an instance of a subclass of C1 that implements I2.

+20
Apr 24 '13 at 8:03
source share

According to JLS 5.5.1 - Listing of a reference type , the rules (s) apply:

  • If T is a class type, then either | S | <: | T | or | T | <: | S |. Otherwise, a compile-time error occurs.

    I2 y = (I2)o3; //compiler complains here !!

In this case, Integer and I2 are not connected in any way. therefore a compile-time error occurs. Also, since Integer is final , there is no relationship between Integer and I2 .

I2 and I1 can be connected due to the fact that both are token interfaces (no contract).

As for compiled code, this rule follows:

  • If S is not a final class (ยง8.1.1), then if there is a supertype X from T and a supertype Y from S such that both X and Y are predictable different parameterized types and that the erasures of X and Y are the same, an error occurs compilation time.

S is o1 and T is I2 .

Hope this helps.

+15
Apr 24 '13 at 8:06
source share



All Articles