在Java 6中,像MyClassMyClass<?>这样的东西被认为是相等的,但是在Java 7中则不一样。

以Java 7为例,我偶然遇到了问题,例如Hamcrest匹配器被赋予了MyClass的实例,而匹配器则期望与MyClass<?>匹配,并且它们得到了编译错误,

no suitable method found for assertThat(MyClass,Matcher<MyClass<?>>)
[ERROR] method Assert.<T#1>assertThat(T#1,Matcher<? super T#1>) is not applicable
[ERROR] (actual argument Matcher<MyClass<?>> cannot be converted to Matcher<? super MyClass> by method invocation conversion)


为什么要改变?原始类型和具有未指定类型参数的泛型类型之间有什么区别?

建议的答案并不能真正解释我在这里所想的。其中一条评论说:“使用未绑定的通配符(例如,在方法签名中)标志着一个承诺,即所讨论的方法知道泛型并将支持该对象的泛型类型。”在这里,我再次感到,如果它只是一个“信号”,那么在编译时就不会引起问题。

我觉得MyClass<?>只是MyClass包含有关其包含或操作内容的信息,但是虽然它是<?>,但没有添加的信息,因此应该将它们视为相等吗?

最佳答案

这似乎与Java 7中修复的compiler bug有关。

您现在收到的编译器错误是正确的。看起来您正在使用通配符泛型类型调用该方法,例如MyClass<?>Matcher<MyClass<?>>。请注意,通配符类型参数的意思是“某些未知类型”,因此这些参数实际上可能是MyClass<String>Matcher<MyClass<Integer>>,这显然是错误的。

使用原始类型,例如plain MyClass选择不使用泛型类型检查,这就是为什么将编译具有原始类型的调用的原因(但在运行时使用ClassCastException可能会失败)。

09-05 14:45
查看更多