接口中的 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
Java casting in interfaces
提问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 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
.
当您转换o1
和o3
时(I2)
,您告诉编译器该对象的类实际上是其声明类型的子类,并且该子类实现了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
couldbe an instance of a subtype of C1
that implements I2
.
该Integer
班是最后的,所以o3
不可能是一个子类的实例Integer
:编译器知道你在说谎。C1
然而不是最终的,所以o1
可能是C1
实现的子类型的实例I2
。
If you make C1
final, 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 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.
那是因为 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 Integer
and I2
are unrelatedin any way, so a compile-time error occurs. Also, because Integer
is final
, there is no relation between Integer
and I2
.
在这种情况下,Integer
和I2
是不相关的任何方式,所以发生编译时间错误。另外,因为Integer
是final
,Integer
和之间没有关系I2
。
I2
and I1
can 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 相同,则发生编译时错误。
S
is o1
and T
is I2
.
S
是o1
并且T
是I2
。
Hope this helps.
希望这可以帮助。
回答by maba
According to JLS chapter 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,否则会发生编译时错误。