将对象的列表转换为类的类型参数列表

时间:2015-11-16 22:10:54

标签: java eclipse generics casting

我正在尝试理解看似类似代码的不同编译结果。似乎可以将List<Object>转换为List<T>,但前提是T不受具体类限制。所以给...

List<Object> bis = new ArrayList<>();

以下内容在class Test<T>class Test<T extends CharSequence>进行编译,但不在class Test<T extends BigDecimal>class Test<T extends BigDecimal & CharSequence>进行编译。

List<T> result = (List<T>) bis;

那么,与类型和接口类型有关的T的区别在哪里呢?

修改

每个请求都有一些完整的代码。这在第9行编译了一个编译器警告。对于result的项目进行操作确实不安全,好像它们是CharSequence的实例导致ClassCastException

    public class Sandbox<T extends CharSequence> {

    public static void main(String[] args) {
        new Sandbox<CharSequence>().foo();
    }

    private void foo() {    
        List<Object> bis = Arrays.asList(Integer.valueOf(1));
        List<T> result = (List<T>) bis;
        System.out.println(result);
    }
}

然而,这根本不编译:

    public class Sandbox<T extends BigDecimal> {

    public static void main(String[] args) {
        new Sandbox<BigDecimal>().foo();
    }

    private void foo() {    
        List<Object> bis = Arrays.asList(Integer.valueOf(1));
        List<T> result = (List<T>) bis;
        System.out.println(result);
    }

}

第9行中的编译器错误:无法将List<Object>强制转换为List<T>

2 个答案:

答案 0 :(得分:0)

这个List<Object> bis = Arrays.asList(Integer.valueOf(1));显然无法编译,因为Arrays.asList(Integer.valueOf(1))会返回List<Integer>,这就是你获得Cannot cast List<Object> to List<T>的原因。

第二种情况,eclipse荒谬地用T extends CharSequence编译,但我用在线编译器检查它并没有编译,所以它很可能是一个日食错误。

答案 1 :(得分:0)

理解此类行为的关键是了解类型擦除实际上做了什么。尽管人们普遍认为它在运行时删除了类型参数 - 但实际上并不是这样。它的作用 - 它减少到声明的参数范围。因此,只要您键入List<T> T已绑定的任何位置,它实际上会缩减为List<[lower-bound-of-T]>。由于Object不是CharSequenceList<Object>无法投放到List<T>(因为它至少意味着List<CharSequence>

为什么会这样?想象一下,您的Sandbox类具有接受T类型参数的方法:

public class Sandbox<T extends CharSequence> {
    void bar(T param) {
        //...
    }
}

bar(T)可以接受T,而T是任何扩展CharSequence的内容,所以基本上在运行时这有效地用作

 void bar(CharSequence param) {
     //...
 }

因此它无法接受简单的Object。这就是为什么仅存在非空的较低参数限制来限制来自...<Object>

的免费演员表

此外,通配符?类型参数可能会让您大吃一惊。它说编译器类似“我不知道它是什么,但我很确定它满足所有界限”。非常奇怪,包括这个事实,你可以(几乎?)投射任何东西,所以它可以实现

  List<Object> bis = Arrays.asList(Integer.valueOf(1));
  List<T> result = (List<T>) (List<?>) bis;

因此,对于带有泛型的设计类,你应该非常非常小心。