我正在努力将一个项目从java 7迁移到8,并且在Mockito中遇到了编译错误“当”我遇到困难的情况下追踪时:
when(queryRunner.query(any(String.class), any(ResultSetHandler.class), anyVararg())).thenReturn(mockedWordResultList);
给我一个编译错误:
java: reference to query is ambiguous both method
<T>query(java.lang.String,java.lang.Object,org.apache.commons.dbutils.ResultSetHandler<T>)
in org.apache.commons.dbutils.QueryRunner and method
<T>query(java.lang.String,org.apache.commons.dbutils.ResultSetHandler<T>,java.lang.Object...)
in org.apache.commons.dbutils.QueryRunner match
此错误发生在构建1.8.0-b128中,但不会发生在1.7.0_45中。我正在使用mockito 1.9.5。
在java 8中使用anyVarArg()
参数匹配的正确方法是什么?
答案 0 :(得分:7)
问题是类型推断已得到改进。 anyVararg()
是一种通用方法,但您在嵌套方法调用中使用它。在Java 8之前,类型推断的限制在将<T> T anyVararg()
作为参数放在另一个方法调用而不插入显式类型参数时强制将<Object> Object anyVararg()
视为处理。
所以只有query(String, ResultSetHandler, Object...)
匹配,因为第三个参数被视为Object
类型。
但现在使用Java 8类型推断可以使用嵌套方法调用。由于<T> T anyVararg()
类型参数<T>
可以只是任何,因此它也可以是ResultSetHandler
。所以query(String,Object,ResultSetHandler)
现在也是匹配候选人。
(在两种情况下,我从外部调用中省略了类型参数<T>
,以减少混淆)
由于我们现在有两种可能的匹配,因此这里适用方法选择的正常程序。是的,这是模棱两可的。第一个参数是相同的String
,但是对于其他两个ResultSetHandler
比Object
更具体,但是当一个候选者接受第二个参数的更具体类型时,另一个参数为第三(和后续)。
很明显,允许方法返回类型的类型参数只是一个模糊性的来源,但像Mockito包含这些方法的API是Java编程的一个极端情况。您必须使用通用方式Matchers.<Desired>anyVararg()
或通过类型转换(Desired)anyVararg()
强制输入类型。