带有Java泛型的双通配符参数化(嵌套通配符)

时间:2014-02-14 12:43:04

标签: java generics

我正在使用来自第三方库(Reflections)的方法,该方法应该找到给定类型的子类型,看起来像

public <T> Set<Class<? extends T>> getSubTypesOf(final Class<T> type) {
...

当来电者代码看起来像

Class<?> type = ...
Set<Class<?>> subTypes = reflections.getSubTypesOf(type);

我收到编译错误:“cannot convert from Set<Class<? extends capture#19-of ?>> to Set<Class<?>>”。以下内容解决了这种情况:

Class<?> type = ...
Set<?> subTypes = reflections.getSubTypesOf(ht);

因此看起来错误的Set<Class<? extends ?>>唯一可能的补救方法是Set<?>,而不是Set<Class<?>>。为什么会这样? 谢谢你对此有任何解释。

4 个答案:

答案 0 :(得分:8)

请改用以下内容:

Set<? extends Class<?>> subTypes = reflections.getSubTypesOf(type);

问题是嵌套通配符不执行type capture。声明Set<Class<?>>表示“一组任何类型的”,而返回的是Set<Class<? extends capture#19-of ?>>,这意味着“一组任何类型的类扩展自< em>某些特定的未知类型“。在这种情况下,“特定未知类型”派生自T的类型参数,该参数从type推断为无限通配符捕获(? Class<?> })。

例如,假装“特定未知类型”为Number

Class<Number> type = ...
Set<Class<?>> subTypes = reflections.getSubTypesOf(type);

此处,getSubTypesOf返回Set<Class<? extends Number>>。该类型可分配给Set<Class<?>>,因为generic types aren't covariant。但是,通配符捕获有助于我们表达协方差,允许类似Set<? extends Class<?>>之类的类型。需要注意的是,除了null之外,我们不能添加任何内容,因为我们不知道它的具体类型。

相关帖子:

类似帖子:

答案 1 :(得分:1)

由于?是通配符,当您插入Class<?>时,该方法返回Set<Class<? extends ?>>(纯粹是理论上的,Java不支持) - 尝试使用具体类型调用该方法(例如Class<Number>),您应该返回Set<Class<? extends Number>>

答案 2 :(得分:1)

以下内容会有所帮助:您的? extends T右侧Class(受T限制)getSubTypesOf将其退回),因此您需要在左侧扩展它:

Class<? extends T> type;
Set<Class<? extends T>> subTypesOf = getSubTypesOf(type);

而不是:

Set<Class<?>> subTypes = reflections.getSubTypesOf(type);

答案 3 :(得分:1)

你必须考虑'?'意思是'未知',而不是'任何'。

Set<Class<?>> subTypes = reflections.getSubTypesOf(type);

子类型是一组“未知”类。它可以是String,Integer,List ......中的任何一个。

getSubTypesOf(type)将返回一组但未知的类。我使用'确定',因为我们知道所有人都会扩展类型。所以它不一样。问题是你似乎不知道编译时的类型类。

Set<Class>也应该有效,但它会显示警告,因为你没有将通用与Class一起使用。

相关问题