一个奇怪的泛型边缘情况与Mockito.when()和泛型类型推断

aar*_*tad 9 java generics mockito

我正在编写一个java.beans.PropertyDescriptor使用Mockito的测试用例,我想模仿getPropertyType()返回任意Class<?>对象的行为(在我的例子中String.class).通常,我会通过调用:

// we already did an "import static org.mockito.Mockito.*"
when(mockDescriptor.getPropertyType()).thenReturn(String.class);
Run Code Online (Sandbox Code Playgroud)

然而,奇怪的是,这不编译:

cannot find symbol method thenReturn(java.lang.Class<java.lang.String>)
Run Code Online (Sandbox Code Playgroud)

但是当我指定类型参数而不是依赖于推理时:

Mockito.<Class<?>>when(mockDescriptor.getPropertyType()).thenReturn(String.class);
Run Code Online (Sandbox Code Playgroud)

一切都是笨拙的海鲂.为什么编译器在这种情况下无法正确推断when()的返回类型?我之前从未必须指定参数.

mat*_*tts 13

PropertyDescriptor#getPropertyType()返回一个对象Class<?>,其中的?意思是"这是一种类型,但我不知道它是什么".我们称这种类型为"X".所以when(mockDescriptor.getPropertyType())创建一个OngoingStubbing<Class<X>>,其方法thenReturn(Class<X>)只能接受对象Class<X>.但是编译器不知道这个"X"是什么类型的,所以它会抱怨你在路过Class任何类型.我认为这与编译器抱怨调用add(...)a的原因相同Collection<?>.

当您明确指定方法Class<?>上的类型时when,您并不是说mockDescriptor.getPropertyType()返回a Class<?>,而是说when返回一个OngoingStubbing<Class<?>>.然后,编译器检查以确保您传入when的任何类型匹配Class<?>; 因为我之前提到的getPropertyType()返回" Class<X>",它当然与Class<?>你指定的匹配.

所以基本上

// the inferred type is Class<"some type">
Mockito.when(mockDescriptor.getPropertyType())

// the specified type is Class<"any type">
Mockito.<Class<?>>when(mockDescriptor.getPropertyType())
Run Code Online (Sandbox Code Playgroud)

在我的IDE中,原始代码的错误消息是

The method thenReturn(Class<capture#1-of ?>) in the type OngoingStubbing<Class<capture#1-of ?>> is not applicable for the arguments (Class<String>)
Run Code Online (Sandbox Code Playgroud)

capture#1-of ?就是我上面描述的"X".