Java casting in interfaces

前端 未结 4 2026
悲&欢浪女
悲&欢浪女 2020-12-02 11:52

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

interface I1 { }
interface I2 { }         


        
相关标签:
4条回答
  • 2020-12-02 12:20

    According to JLS 5.5.1 - Reference Type casting, the rule(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, an Integer and I2 are unrelated in any way, so a compile-time error occurs. Also, because Integer is final, there is no relation between Integer and I2.

    I2 and I1 can be related due to both being a marker interface (there are no contract).

    As for the compiled code, the rule follows:

    • 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.

    S is o1 and T is I2.

    Hope this helps.

    0 讨论(0)
  • 2020-12-02 12:21

    When you cast o1 and o3 with (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 a subclass of Integer: the compiler knows that you're lying. C1 however is not final, so o1 could be an instance of a subtype of C1 that implements I2.

    If you make 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
         }
    }
    
    0 讨论(0)
  • 2020-12-02 12:32

    That's because class Integer is final and C1 is not. Thus, an Integer object cannot implement I2, while a C1 object could if it is an instance of a subclass of C1 that implements I2.

    0 讨论(0)
  • 2020-12-02 12:38

    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.

    0 讨论(0)
提交回复
热议问题