接口中的 Java 转换

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16186474/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-16 05:40:16  来源:igfitidea点击:

Java casting in interfaces

javainterfacecasting

提问by geo

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 { }
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 !!
     }
}

采纳答案by WilQu

When you cast o1and o3with (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.

当您转换o1o3(I2),您告诉编译器该对象的类实际上是其声明类型的子类,并且该子类实现了I2.

The Integerclass is final, so o3cannot be an instance of a subclass of Integer: the compiler knows that you're lying. C1however is not final, so o1couldbe an instance of a subtype of C1that implements I2.

Integer班是最后的,所以o3不可能是一个子类的实例Integer:编译器知道你在说谎。C1然而不是最终的,所以o1可能C1实现的子类型的实例I2

If you make C1final, the compiler will complain too:

如果你C1最终,编译器也会抱怨:

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
     }
}

回答by Etienne Miret

That's because class Integeris final and C1is 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.

那是因为 classInteger是 final 而C1不是。因此,Integer 对象不能实现 I2,而 C1 对象可以,如果它是实现 I2 的 C1 的子类的实例。

回答by Buhake Sindi

According to JLS 5.5.1 - Reference Type casting, the rule(s) apply:

根据JLS 5.5.1 - 参考类型转换,规则适用:

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

  • 如果 T 是类类型,则 |S| <: |T|, 或 |T| <: |S|。否则,会发生编译时错误。

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

In this case, an Integerand I2are unrelatedin any way, so a compile-time error occurs. Also, because Integeris final, there is no relation between Integerand I2.

在这种情况下,IntegerI2不相关的任何方式,所以发生编译时间错误。另外,因为IntegerfinalInteger和之间没有关系I2

I2and I1can be related due to both being a marker interface (there are no contract).

I2并且I1由于两者都是标记界面(没有合同)而可能相关。

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 不是最终类(第 8.1.1 节),那么,如果存在 T 的超类型 X 和 S 的超类型 Y,使得 X 和 Y 都是可证明不同的参数化类型,并且 X 的擦除和 Y 相同,则发生编译时错误。

Sis o1and Tis I2.

So1并且TI2

Hope this helps.

希望这可以帮助。

回答by maba

According to JLS chapter 5

根据JLS 第 5 章

5.5.1. Reference Type Casting

5.5.1. 引用类型转换

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.

给定一个编译时引用类型 S(源)和一个编译时引用类型 T(目标),如果由于以下规则没有发生编译时错误,则存在从 S 到 T 的强制转换。如果 T 是接口类型:

如果 S 不是最终类(第 8.1.1 节),那么,如果存在 T 的超类型 X 和 S 的超类型 Y,使得 X 和 Y 都是可证明不同的参数化类型,并且 X 的擦除和 Y 相同,则发生编译时错误。

否则,转换在编译时总是合法的(因为即使 S 没有实现 T,S 的子类也可能)。

如果 S 是 final 类(第 8.1.1 节),则 S 必须实现 T,否则会发生编译时错误。