当方法的签名定义为Collection <class> </class> </subclass>时,为什么方法不能采用Collection <subclass>

时间:2011-08-06 05:41:15

标签: java inheritance collections

我有一个获取SResource对象列表的方法

public static List<STriple> listTriples(List<SResource> subjects){
//... do stuff
}

为什么我不能这样做

List<IndexResource> resultsAsList = new ArrayList<IndexResource>();
    resultsAsList.addAll(allResults.keySet()); // I could possible not use lists and just use sets and therefore get rid of this line, but that is a different issue
List<STriple> triples = new ArrayList<STriple>();
    triples = TriplesDao.listTriples(resultsAsList);

(编译器告诉我必须让triples使用SResource对象。)

当IndexResource是SResource的子类

public class IndexResource extends SResource{ 
// .... class code here
}

我原本以为这是可能的,所以也许我做错了什么。如果你建议,我可以发布更多代码。

3 个答案:

答案 0 :(得分:23)

您可以使用wildcards

执行此操作
public static List<STriple> listTriples(List<? extends SResource> subjects){
    //... do stuff
}

新声明使用有界通配符,它表示泛型参数可以是SResource,也可以是扩展它的类型。

作为以这种方式接受List<>的交换,“do stuff”不能包含插入subjects。如果您只是阅读方法中的subjects,那么此更改可以为您提供所需的结果。

编辑:要查看为什么需要使用通配符,请考虑这个(Java中的非法)代码:

List<String> strings = new ArrayList<String>();
List<Object> objList = string; // Not actually legal, even though string "is an" object
objList.add(new Integer(3)); // Oh no! We've put an Integer into an ArrayList<String>!

这显然不是类型安全的。但是,使用wilcards,可以执行此操作:

List<String> strings = new ArrayList<String>();
string.add("Hello");
List<? extends Object> objList = strings; // Works!
objList.add(new Integer(3)); // Compile-time error due to the wildcard restriction

答案 1 :(得分:6)

你不能这样做,因为generics are not "covariant"List<Integer>不是List<Number>的子类,尽管IntegerNumber的子类}}

答案 2 :(得分:1)

对于那些无法添加通配符的人,这应该可行。

List<Integer> list = new ArrayList<Integer>();
new ArrayList<Number>(list);