作者:小鱼儿太疯癫 | 来源:互联网 | 2022-12-02 19:10
我有一个简单的foo
类,我能够转换到集合接口(Map
或者List
),没有任何编译器错误.请注意,Foo
类不实现任何接口或扩展任何其他类.
public class Foo {
public List getCollectionCast() {
return (List) this; // No compiler error
}
public Map getCollection2Cast() {
return (Map) this; // No compiler error
}
public Other getCast() {
return (Other)this; // Incompatible types. Cannot cast Foo to Other
}
public static class Other {
// Just for casting demo
}
}
当我尝试将类转换为集合时,为什么Java编译器不会返回不兼容的类型错误Foo
?
Foo
没有实现Collection
.我期望一个不兼容的类型错误,因为给定当前Foo
类签名,这不能是一个Collection
.
1> T.J. Crowder..:
这不是因为它们是集合类,而是因为它们是接口.Foo
不实现它们,但它的子类可以.因此,这不是编译时错误,因为这些方法可能对子类有效.在运行时,如果this
不是实现这些接口的类,那自然就是运行时错误.
如果List
改为ArrayList
,那么你也会得到编译时错误,因为Foo
子类可以实现List
,但不能扩展ArrayList
(因为Foo
没有).类似地,如果你做Foo
final
,编译器会给你的接口强制转换错误,因为它知道它们永远不会是真的(因为Foo
不能有子类,并且不实现这些接口).
2> ernest_k..:
编译器不会阻止代码将类型转换为接口,除非它可以确定关系是不可能的.
如果目标类型是接口,那么它是有意义的,因为类扩展Foo
可以实现Map
.但请注意,这仅适用于Foo
不行final
.如果你宣布你的班级final class Foo
,该演员阵容将无效.
如果目标类型是一个类,那么在这种情况下它只会失败(尝试(HashMap) this
),因为编译器肯定知道Foo
和之间的关系HashMap
是不可能的.
作为参考,这些规则在JLS-5.5.1中描述(T =目标类型 - Map
,S =源类型 - Foo
)
如果T [目标类型]是接口类型:
如果S不是最终类(第8.1.1节),那么,如果存在T的超类型X和S的超类型Y,则X和Y都是可证明的不同参数化类型,并且X的擦除和Y相同,发生编译时错误.
否则,强制转换在编译时总是合法的(因为即使S没有实现T,S的子类也可能).
如果S是最终类(第8.1.1节),那么S必须实现T,否则会发生编译时错误.
请注意引用文本中的粗体斜体注释.