无法推断通用类型“?super SomeClass”
Can't infer generic type "? super SomeClass"
在尝试用我的通用方法找出问题后,我得到了以下代码:
Map<String, BiConsumerThatThrows<CheckPayment, XMLEventReader>> a = CheckPayment.childMapper;
BiConsumerThatThrows<CheckPayment, XMLEventReader> a1 = a.get("1");
BiConsumerThatThrows<? super CheckPayment, XMLEventReader> b1 = a1;
Map<String, BiConsumerThatThrows<? super CheckPayment, XMLEventReader>> b = new HashMap<>();
b.put("1", b1);
b = a;
它不会编译并出现以下错误(我已对其进行格式化以使其更具可读性):
[ERROR] /D:/lalala/MyClass.java:[152,27]
incompatible types:
java.util.Map<
java.lang.String,
blablabla.BiConsumerThatThrows<
blablabla.CheckPayment,
javax.xml.stream.XMLEventReader
>
>
cannot be converted to
java.util.Map<
java.lang.String,
blablabla.BiConsumerThatThrows<
? super blablabla.CheckPayment,
javax.xml.stream.XMLEventReader
>
>
最令人惊讶的是,它仅在给定代码段的最后一行崩溃。
为什么会这样?执行此类分配可以做什么?
我正在使用 Oracle JDK 1.8u40 x64。
P.S。这是简化的示例:
Set<Set<String>> sets = new HashSet<>();
Set<Set<? super String>> sets2 = new HashSet<>();
sets2 = sets;
错误:
incompatible types: java.util.Set<java.util.Set<java.lang.String>> cannot be converted to java.util.Set<java.util.Set<? super java.lang.String>>
P.P.S。即使这样也行不通:
Set<Set<Object>> sets2 = new HashSet<Set<String>>();
为什么?
问题是泛型类型参数约束对于嵌套约束不是透明的。 Map<String, List<Integer>>
是与 Map<String, List<? super Integer>>
不同的类型,您不能将一个分配给另一个。这就是您在这里遇到的问题。
要修复它,您需要使用 extends
:
将通配符一直应用到顶级泛型声明
Map<String, ? extends List<? super Integer>> m = new HashMap<String, List<Integer>>()
请注意,这是 extends
,而不是 super
,因为 List<Integer>
是 sub 类型的 List<? super Integer>
(我也觉得这很费脑筋)。所以在你的情况下,这将是:
Map<String, ? extends BiConsumerThatThrows<? super CheckPayment, XMLEventReader>> b = ...
和简化示例:
Set<? extends Set<? super String>> sets2 = new HashSet<>();
这可能有助于理解这一点:http://www.angelikalanger.com/GenericsFAQ/FAQSections/TypeArguments.html#FAQ104
在尝试用我的通用方法找出问题后,我得到了以下代码:
Map<String, BiConsumerThatThrows<CheckPayment, XMLEventReader>> a = CheckPayment.childMapper;
BiConsumerThatThrows<CheckPayment, XMLEventReader> a1 = a.get("1");
BiConsumerThatThrows<? super CheckPayment, XMLEventReader> b1 = a1;
Map<String, BiConsumerThatThrows<? super CheckPayment, XMLEventReader>> b = new HashMap<>();
b.put("1", b1);
b = a;
它不会编译并出现以下错误(我已对其进行格式化以使其更具可读性):
[ERROR] /D:/lalala/MyClass.java:[152,27]
incompatible types:
java.util.Map<
java.lang.String,
blablabla.BiConsumerThatThrows<
blablabla.CheckPayment,
javax.xml.stream.XMLEventReader
>
>
cannot be converted to
java.util.Map<
java.lang.String,
blablabla.BiConsumerThatThrows<
? super blablabla.CheckPayment,
javax.xml.stream.XMLEventReader
>
>
最令人惊讶的是,它仅在给定代码段的最后一行崩溃。
为什么会这样?执行此类分配可以做什么?
我正在使用 Oracle JDK 1.8u40 x64。
P.S。这是简化的示例:
Set<Set<String>> sets = new HashSet<>();
Set<Set<? super String>> sets2 = new HashSet<>();
sets2 = sets;
错误:
incompatible types: java.util.Set<java.util.Set<java.lang.String>> cannot be converted to java.util.Set<java.util.Set<? super java.lang.String>>
P.P.S。即使这样也行不通:
Set<Set<Object>> sets2 = new HashSet<Set<String>>();
为什么?
问题是泛型类型参数约束对于嵌套约束不是透明的。 Map<String, List<Integer>>
是与 Map<String, List<? super Integer>>
不同的类型,您不能将一个分配给另一个。这就是您在这里遇到的问题。
要修复它,您需要使用 extends
:
Map<String, ? extends List<? super Integer>> m = new HashMap<String, List<Integer>>()
请注意,这是 extends
,而不是 super
,因为 List<Integer>
是 sub 类型的 List<? super Integer>
(我也觉得这很费脑筋)。所以在你的情况下,这将是:
Map<String, ? extends BiConsumerThatThrows<? super CheckPayment, XMLEventReader>> b = ...
和简化示例:
Set<? extends Set<? super String>> sets2 = new HashSet<>();
这可能有助于理解这一点:http://www.angelikalanger.com/GenericsFAQ/FAQSections/TypeArguments.html#FAQ104