声明通用方法,需要澄清

时间:2012-08-02 13:24:43

标签: java generics

考虑以下两种方法声明:

1. public abstract <T extends MetaData> List<T> execute();
2. public abstract List<? extends MetaData>  execute();

两者似乎都返回扩展MetaData的对象列表

他们之间有什么区别?

3 个答案:

答案 0 :(得分:12)

在第一种情况下,您将允许Java使用类型推断并推断每个呼叫站点的T类型。

在第二种情况下,您将始终获得List<? extends MetaData>,因此无法将其分配给任何较窄类型的变量,例如List<IntegerMetaData>

答案 1 :(得分:0)

如果有MetaData的任何子类型,则第一个版本只能返回空列表或null。第二个版本可能会返回一个包含MetaData及其子类型实例的列表。

示例:说ABMetaData的子类型,execute返回包含A实例的列表。调用者可能像这样调用execute:

List<B> list = execute(); // the second version does not allow this

来电者说他想要一个B的列表,但得到一个包含A的列表。由于类型擦除,execute的实现无法知道调用者要求的内容。因此,无法实现第一个版本(除了返回null或空列表)。

答案 2 :(得分:-1)

在示例1中,您不能返回其泛型类型为T的List,例如:

@Override
public <T extends MetaData> List<T> execute() {
    List<T> l = new ArrayList<T>();
    return l; 
}

在示例2中,您可以返回其泛型类型仅为MetaData的List,例如:

@Override
public List<? extends MetaData> execute2() {
    List<MetaData> l = new ArrayList<MetaData>();
    return l;
}

有什么区别?在第一种情况下,方法具有泛型类型T,并且必须返回与该类型相关的内容。在第二种情况下,您只返回一个泛型类型,但该方法本身没有泛型类型。