如何通过Java Generics将子类型添加到超类型列表中

时间:2013-05-19 10:21:48

标签: java generics

我正在尝试做一些编译好的事情:

public interface Training {
    public void train();
}

public class JavaTraining implements Training{

    @Override
    public void train() {
        // TODO Auto-generated method stub

    }


}

import java.util.*;

public class TestClass {

    /**
     * @param args
     */
    public static void main(String[] args) {
        List<Training> trainingList = new ArrayList<Training>();
        trainingList.add(new JavaTraining());
        for(Training trainingItem : trainingList){
            trainingItem.train();
        }

    }

}

这个编译很好并且也可以运行。

但是当我尝试更改下面的main方法时,它会产生编译时错误。

为什么?

import java.util.*;

public class TestClass {

    /**
     * @param args
     */
    public static void main(String[] args) {
        List<Training> trainingList = new ArrayList<JavaTraining>();
    }

}

编译时错误是:

“类型不匹配:无法从ArrayList转换为List”

我甚至读过一篇帖子here。但这并不能说明我的疑问。

问题不是this的重复,因为我没有在任何地方使用

List<? extends Training>

但它仍然接受JavaTraining的对象。怎么样?

2 个答案:

答案 0 :(得分:5)

这就是为什么你不能这样做的原因:

List<JavaTraining> jt = new ArrayList<JavaTraining>(); // So far so good
List<Training> trainingList = jt; // This is what you did; let's pretend it compiles
trainingList.add(new CobolTraining()); // The compiler must allow this, because `CobolTraining` is a `Training`.

上述问题是,它允许您将CobolTraining放入jtJavaTraining列表。

答案 1 :(得分:0)

这是由于仿制药的设计原因。 ArrayList<JavaTraining>不会延伸ArrayList<Training>

你应该做

  List<? extends Training> trainingList = new ArrayList<JavaTraining>();

检查通配符的使用情况。