我在有效使用泛型时遇到了麻烦。在大多数情况下,遇到以下问题时,我最终会找到另一种方法来完成所需的工作,但是这让我感到自己对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)”。

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

最佳答案

您如何知道两个示例中的TValidTypeOtherValidType的超类?
T可能是完全不同的类,也恰好实现了I1I2接口,在这种情况下,您无法在其中放置ValidTypeOtherValidType实例。

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

List<OtherValidType> list = Foo.getList();

应该很清楚TOtherValidType,但是您试图在其中插入ValidType,但是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是什么类型,就无法知道具体的已知类ValidTypeOtherValidType是否可分配给它。

10-07 13:51