为什么不能将包含泛型类型的泛型类型分配给通用类型的通配符类型

时间:2009-09-25 09:58:54

标签: java generics

很抱歉,如果标题看起来令人困惑,但有些例子是有序的。

假设我有一些带有泛型类型参数的Java类:

public class GenericClass<T> {
}

我可以创建一个类型的变量来存储一个对象,并将泛型参数设置为String。 Java还允许我将该变量分配给另一个变量,但将generic参数设置为通配符<?>类型:

GenericClass<String> stringy = ...
GenericClass<?> generic = stringy; // OK

但是,当使用具有泛型参数的类时,如果将该参数的类型设置为泛型,则不能将该类的对象分配给具有相同类型/泛化类型的后者(内部) / nested)参数是通配符类型<?>

GenericClass<GenericClass<String>> stringy = ...
GenericClass<GenericClass<?>> generic = stringy; // Compile Error

// And just in case that is confusing, a more
// realistic example involving Collections:
List<GenericClass<String>> stringy = ...
List<GenericClass<?>> generic = stringy; // Compile Error

具体的编译错误是:

Type mismatch: cannot convert from List<GenericClass<String>> to List<GenericClass<?>>

直觉上我认为有问题的作业不应成为问题。那么为什么这个任务有问题呢?

2 个答案:

答案 0 :(得分:8)

您面临的问题是Covariance

List<GenericClass<String>> stringy = ...
List<GenericClass<?>> generic = stringy;
generic.add(new GenericClass<Integer>());

如果这不是编译错误,则可以使用最后一行代码。

你可以通过这样做来解决错误:

 List<? extends GenericClass<?>> generic = stringy;

但你也不能使用add,因为你真的不知道? extends GenericClass<?>是什么(Covariance再一次)。在这种情况下,您只能枚举列表并期望GenericClass<?>

答案 1 :(得分:4)

从技术上讲,这是因为List<GenericClass<String>>不是List<GenericClass<?>>的子类型。为了使它工作,你可以做类似

的事情
List<? extends GenericClass<?>> generic = stringy

应该按预期工作(虽然非常难看......)。

例如,请参阅this SO question了解更多详情