为什么Java让您强制转换为集合?

时间:2018-10-08 08:23:13

标签: java collections interface casting

我有一个简单的foo类,并且能够强制转换为集合接口(MapList)而没有任何编译器错误。 请注意,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类强制转换为集合时,为什么Java编译器不返回不兼容类型错误

Foo未实现Collection。我不希望看到类型不兼容的错误,因为给定当前的Foo类签名,所以它不能是Collection

3 个答案:

答案 0 :(得分:125)

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

如果将List<String>更改为ArrayList<String>,您也会收到编译时错误,因为Foo子类可以实现List,但可以请勿扩展ArrayList(因为Foo不扩展)。同样,如果您制作Foo final,则编译器会因接口强制转换而给您一个错误,因为它知道它们永远不会为真(因为Foo不能有子类,并且不会没有实现这些接口)。

答案 1 :(得分:47)

除非可以确定无法建立关系,否则编译器不会阻止代码将类型强制转换为接口。

如果目标类型是接口,那么这是有道理的,因为扩展Foo的类可以实现Map<String, String>。但是,请注意,这仅适用于 Foo而不是final 。如果您使用final class Foo声明了自己的课程,则该转换将无效。

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

作为参考,这些规则在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的子类也可能会这样)。

    < / li>   
  • 如果S是最终类(第8.1.1节),则S必须实现T,否则会发生编译时错误。

  •   

请注意带引号的文本中的 粗体 注释。

答案 2 :(得分:-6)

https://docs.oracle.com/javase/8/docs/api/java/util/List.html

  

所有超级接口:       集合,可迭代

Foo是列表就是集合。