为什么Java允许您强制转换到集合?
我有一个简单的为什么Java允许您强制转换到集合?,java,collections,interface,casting,Java,Collections,Interface,Casting,我有一个简单的foo类,我能够在没有任何编译器错误的情况下转换到集合接口(映射Map或List)。 请注意,Foo类不实现任何接口或扩展任何其他类 public class Foo { public List<String> getCollectionCast() { return (List<String>) this; // No compiler error } public Map<String, Strin
foo
类,我能够在没有任何编译器错误的情况下转换到集合接口(映射Map
或List
)。
请注意,Foo
类不实现任何接口或扩展任何其他类
public class Foo {
public List<String> getCollectionCast() {
return (List<String>) this; // No compiler error
}
public Map<String, String> getCollection2Cast() {
return (Map<String, String>) 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
}
}
公共类Foo{
公共列表getCollectionCast(){
返回(列出)此;//没有编译器错误
}
公共地图getCollection2Cast(){
返回(映射)此;//没有编译器错误
}
公共其他getCast(){
返回(其他)this;//不兼容的类型。无法将Foo强制转换为其他类型
}
公共静态类其他{
//只是为了试演
}
}
当我尝试将Foo
类强制转换为集合时,为什么Java编译器不返回不兼容类型错误
Foo
未实现收集
。我预计会出现不兼容的类型错误,因为给定当前的Foo
类签名,这不能是集合
这不是因为它们是集合类,而是因为它们是接口Foo
没有实现它们,但它的子类可以实现。所以这不是编译时错误,因为这些方法可能对子类有效。在运行时,如果这个不是实现这些接口的类,那么它自然是一个运行时错误
如果您将List
更改为ArrayList
,您也会因此得到一个编译器时间错误,因为Foo
子类可以实现List
,但不能扩展ArrayList
(因为Foo
没有)。类似地,如果您将Foo
final
,编译器将为您的接口强制转换提供一个错误,因为它知道它们永远不会为真(因为Foo
不能有子类,也不能实现这些接口)。编译器不会阻止代码将类型强制转换为接口,除非它能确定这种关系是不可能的
如果目标类型是接口,那么它是有意义的,因为扩展Foo
的类可以实现Map
。但是,请注意,这只在Foo
不是最终版本时起作用。如果您使用最终类Foo
声明类,则该转换将不起作用
如果目标类型是一个类,那么在这种情况下它将失败(尝试(HashMap)this
),因为编译器肯定知道Foo
和HashMap
之间的关系是不可能的
为了便于参考,这些规则在(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,否则会发生编译时错误
请注意引用文本中的粗体斜体注释。
所有超级界面:
收藏,可编辑
Foo是一个列表,也是一个集合。您可以编写Foo
的子类来实现List
或Map
@istovatis,因为Other
是一个类,Foo
的子类也不能扩展Other
。在上面的问题中,有两个类实现了两个接口。在这里,foo类没有实现任何接口。此外,在您提供的问题中,编译器在一个接口强制转换中抱怨,而在另一个接口强制转换中没有抱怨。因此,我们必须处理两个不同的示例,不,Foo
既不是列表
也不是集合