为什么Java编译器在类字面量上会给出“rawtypes”警告?

8
我正在使用Mockito编写一些测试,以下是我正在使用的代码片段:

ArgumentCaptor<LinkedList> captor = ArgumentCaptor.forClass(LinkedList.class); 

这段代码可以成功编译和运行,除了一个警告:“captor”是原始类型,建议将其替换为类似于以下内容的内容:
ArgumentCaptor<LinkedList<String>> captor = ArgumentCaptor.forClass(LinkedList<String>.class);

问题在于LinkedList<String>.class不存在,因此赋值语句的右侧永远无法编译通过。
假设抑制警告不够优雅,是否有更优雅的解决方案?如果没有,为什么编译器会警告我一个我实际上无法修复的问题?

你尝试过使用 LinkedList<?> 吗? - jtahlborn
2
我认为你不会得到一个你喜欢的答案。泛型已经使这门语言的复杂度惊人地增加了(通配符,<>, 递归边界没有人能理解,泛型方法, extendssuper等等),所以要庆幸它并没有更糟糕。如果要使它在没有警告的情况下编译通过,就需要让语言变得更加复杂(具体来说,LinkedList<String>.class必须成为合法代码),所以从某种意义上说,你应该庆幸它不能工作。我认为你只需要压制这个警告,然后忘掉它。 - Paul Boddington
2
@pbabcdefp 实际上,Mockito 中有一种机制专门用于解决泛型问题。您只需对声明进行注释,然后请求 Mockito 为您创建所有内容即可。 - azurefrog
1
@Joe,我认为在这里使用TypeToken方法并不合适,因为注解方法更加简洁。Captor API文档甚至特别提到了这种情况:“使用@Captor注解的优点之一是可以避免与捕获复杂泛型类型相关的警告。” - azurefrog
显示剩余4条评论
1个回答

7

在Mockito中有一个@Captor注解,旨在帮助你避免类似于这样的警告。

使用它,你不需要手动new你的ArgumentCaptor。你只需要用注解声明它,然后调用MockitoAnnotations.initMocks(this);来“自动”创建你的captor。

而不是这样:

ArgumentCaptor<LinkedList> captor = ArgumentCaptor.forClass(LinkedList.class); 

做这个:
@Captor
ArgumentCaptor<LinkedList<String>> captor;

@Before
public void init() {
   // initialize fields annotated with Mockito annotations
   MockitoAnnotations.initMocks(this);  
}

1
现在应该使用@RunWith(MockitoJUnitRunner.class)或新的MockitoJunitRule来替代MockitoAnnoyions.initMocks(this),它们更安全。更不用说命名更好,不仅限于模拟对象。 - bric3
感谢Mockito的提示。 - jwepurchase
我会接受这个答案,因为虽然我并不是在问Mockito的问题,但它让我找到了解决方法。(我编辑了答案,添加了指向该解决方案的链接)。但是这是一个多么好的解决方案啊!如果我在编写代码时要摆脱编译器警告,我不太可能费那么大劲。 - jwepurchase

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接