如何将元素添加到List <T扩展I1和I2>?

时间:2019-07-08 04:48:04

标签: java generics

我无法有效使用泛型。在大多数情况下,遇到以下问题时,我最终会找到另一种方法来完成所需的工作,但这使我感到自己对Java中的泛型用法缺乏了解。

如果我想创建一个返回List的方法,T将在其中扩展任何内容,那么我会收到一个编译器错误,指出我添加到列表中的任何内容都无法转换为T。

请参见以下代码作为示例:

public interface I1 {
}

public interface I2 {
}

public class ValidType implements I1, I2 {
}

public class OtherValidType extends ValidType {
}

public class Foo {
    private static <T extends I1 & I2> List<T> getList() {
        List<T> list = new ArrayList<>();
        list.add(new ValidType());
        list.add(new OtherValidType());
        return list;
    }
}

编译器甚至不让我做一些更简单的事情,例如:

public class Foo {
    private static <T extends ValidType> List<T> getList() {
        List<T> list = new ArrayList<>();
        list.add(new ValidType());
        return list;
    }
}

在第二个示例中,我知道我可以做一个List,并且继承该类型的类将被接受,这只是为了试图了解我对泛型的理解在哪里出了错。

例如,上述所有方法都会产生编译错误“列表中的add(T)无法应用于(ValidType)”。

在哪里我误解了泛型作为返回类型/类型参数的用法?

2 个答案:

答案 0 :(得分:4)

您怎么知道两个示例中的TValidTypeOtherValidType的超类?

T可能是完全不同的类,也恰好实现了接口I1I2,在这种情况下,您不能放置ValidType和{{1}的实例}。

对于第二个示例,请尝试:

OtherValidType

应该清楚,List<OtherValidType> list = Foo.getList(); T,但是您试图在其中插入OtherValidType,但是ValidType不是{ {1}}(它是超类)。

在某些情况下,您可以使用该构造,例如:

ValidType

但是,如果您不知道OtherValidType是什么类型,就无法知道具体的已知类private static <T extends I1 & I2> List<T> getList(T a, T b) { List<T> list = new ArrayList<>(); list.add(a); list.add(b); return list; } T是否可分配给它。

答案 1 :(得分:0)

对于此方法:

private static <T extends ValidType> List<T> getList() {
    List<T> list = new ArrayList<>();
    list.add(new ValidType());
    return list;
}

这就像您要声明(如果可能的话):

List<T extends ValidaType> list = new ArrayList<>();

您只能放入List这样的T;尽管该语言不允许此声明。另一方面,该语言确实允许使用所谓的通配符声明类似这样的内容(此处仅用于证明观点):

List<? extends ValidType> list = new ArrayList<>();
ValidType vt = list.get(0);

您仍然不能放任何东西(可以null,但这不是重点),但是当您检索来自该List的东西时,您只能得到ValidType,这就是您得到的执行。您可以将任何子类型(如T放入其中,但只能检索超类型,因为您实际上并不知道在其中放置了什么子类型。因此,您的方法:

private static <T extends ValidType> List<T> getList() {
    List<T> list = new ArrayList<>();
    return list;
} 

在被调用时将被强制执行

List<OtherValidType> l1 = getList(); // compiles
List<String> l2 = getList(); // does not compile