为什么在使用时需要使用强制转换器'扩展'?

时间:2018-03-09 10:33:12

标签: java

使用List<T>时,为什么需要投放到T extends A

class A{}
public <T extends A> List<T> someMethod() {
    List<A> list = new ArrayList<>();
    List<T> result1 = list; // !! Does not compile, why?
    List<T> result2 = (List<T>) list; // ok, but why need cast?

    return  result2;
}

1 个答案:

答案 0 :(得分:2)

阅读the documentation about "Wildcards and Subtyping":在您的示例中,List<T>List<A>的子类型。您无法将实例分配给其子类型的变量。

想象一个更简单的案例:NumberInteger

Number n = ...;
Integer i;
i = n;  // error
i = (Integer) n;

你可以抛弃编译错误,只要你知道你的变量发生了什么,它就能正常工作。如果nDouble,则会得到ClassCastException

对于像示例中的集合一样,强制转换始终有效,因为在运行时不会检查泛型类型信息,即它只是从List强制转换为List

但是当你有像List这样的泛型类型时,还有另一个复杂程度:使用泛型类型,你可以保证列表包含的内容(想象它就像对自己的承诺,开发人员)使用代码和编译器)。通过分配更广泛的&#34;列表,以后再使用时会遇到麻烦。

class Apple extends Fruit
class Orange extends Fruit

List<Fruit> fruitBasket = Arrays.asList(new Orange(), new Apple());
List<Apple> applesOnly;
applesOnly = (List<Apple>) fruitBasket;

for (Apple apple : applesOnly) // ClassCastException because of the Orange in fruitBasket

在此示例中,您通过分配applesOnly打破了fruitBasket仅包含苹果的承诺。这就是为什么大多数IDE在投射泛型时至少会给你一个警告的原因。