2

MyClass在 Java 6 中,类似的东西MyClass<?>被认为是平等的,但在 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关于它包含或操作的信息,但是虽然它是<?>,但没有附加信息,所以它们应该被认为是平等的?

4

3 回答 3

3

这似乎与Java 7 中修复的编译器错误有关。

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

使用原始类型,例如,plainMyClass 选择退出泛型类型检查,这就是为什么使用原始类型的调用将编译(但可能在运行时失败并带有 a ClassCastException)。

于 2013-05-16T06:27:52.333 回答
1

编辑

MyClass并且MyClass<?>在 Java 6 中不一样,

看到这个链接

为了向后兼容,允许将参数化类型分配给其原始类型:

MyClass<String> stringBox = new MyClass<>();
MyClass rawBox = stringBox;               // OK

但是,如果将原始类型分配给参数化类型,则会收到警告:

  MyClass rawBox = new MyClass();

  // rawBox is a raw type of MyClass<T>


  MyClass<Integer> intBox = rawBox;    

// warning: unchecked> conversion

MyClass不是泛型类型,MyClass<?>是泛型类型类,这意味着,MyClass是包含另一个类的类型,

例如,它在Java中很常见,我们就这样做

List<String> listofString = new ArrayList<String>();

这意味着变量 listofString 是 List 的一个对象,它将其内容限制为仅 String 类型的对象。<String>告诉泛型。

于 2013-05-16T06:02:32.610 回答
1

正如 Jon Skeet 所说,他们不被认为是平等的,在我看来这是不正确的。如果我尝试使用 Java 6 和 Java 7,我看不出有什么区别——你是怎么尝试的?

要了解原始类型和泛型类型之间的区别,只需查看此帖子(向下滚动到“原始类型与用作类型参数有何不同?”): 什么是原始类型,我们为什么不应该用它?

于 2013-05-16T06:05:49.427 回答