为什么Java允许你转换为集合?

ist*_*tis 65 java collections casting interface

我有一个简单的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
    }

}
Run Code Online (Sandbox Code Playgroud)

当我尝试将类转换为集合时,为什么Java编译器不会返回不兼容的类型错误Foo

Foo没有实现Collection.我期望一个不兼容的类型错误,因为给定当前Foo类签名,这不能是一个Collection.

T.J*_*der 124

这不是因为它们是集合类,而是因为它们是接口.Foo不实现它们,但它的子类可以.因此,这不是编译时错误,因为这些方法可能对子类有效.在运行时,如果this不是实现这些接口的类,那自然就是运行时错误.

如果List<String>改为ArrayList<String>,那么你也会得到编译时错误,因为Foo子类可以实现List,但不能扩展ArrayList(因为Foo没有).类似地,如果你做Foo final,编译器会给你的接口强制转换错误,因为它知道它们永远不会是真的(因为Foo不能有子类,并且不实现这些接口).


ern*_*t_k 47

编译器不会阻止代码将类型转换为接口,除非它可以确定关系是不可能的.

如果目标类型是接口,那么它是有意义的,因为类扩展Foo可以实现Map<String, String>.但请注意,这仅适用于Foo不行final.如果你宣布你的班级final class Foo,该演员阵容将无效.

如果目标类型是一个类,那么在这种情况下它只会失败(尝试(HashMap<String, String>) this),因为编译器肯定知道Foo和之间的关系HashMap是不可能的.

作为参考,这些规则在JLS-5.5.1中描述(T =目标类型 - Map<String, String>,S =源类型 - Foo)

如果T [目标类型]是接口类型:

  • 如果S不是最终类(第8.1.1节),那么,如果存在T的超类型X和S的超类型Y,则X和Y都是可证明的不同参数化类型,并且X的擦除和Y相同,发生编译时错误.
    否则,强制转换在编译时总是合法的(因为即使S没有实现T,S的子类也可能).

  • 如果S是最终类(第8.1.1节),那么S必须实现T,否则会发生编译时错误.

请注意引用文本中的粗体斜体注释.