java - 需要解释 : Generic friendliness to avoid casting, 这在 Java 8 中不再需要

标签 java generics java-8 mockito

* @deprecated With Java 8 this method will be removed in Mockito 3.0. This method is only used for generic
 * friendliness to avoid casting, this is not anymore needed in Java 8.
 */
public static <T> List<T> anyListOf(Class<T> clazz) {
    return anyList();
}

我正在研究 Mockito 源代码,发现了这个已弃用的方法,任何人都可以解释一下 Java 8 中是如何处理它的。如果有一个例子,我将不胜感激,如何在不使用此方法作为参数的情况下调用泛型方法为了它。

@Test
public void getDataTest() {
    when(dataSetDao.getDataSetList()).thenReturn(getMockDataSetList());
    when(serviceUtil.getDataFromEndpoint(anyInt(), anyList(), anyString(), any(TypeToken.class), anyString())).thenReturn(getMockDataList());
    List<Data> dataList = noaaDataService.getData();
    verify(serviceUtil, times(11)).getDataFromEndpoint(anyInt(), anyList(), anyString(), any(TypeToken.class), anyString());
    assertEquals(11, dataList.size());

}

private <T> List<T> getMockDataList() {
    List<Data> dataList = new ArrayList<>();
    for (int i = 0; i < 1; ++i) {
        dataList.add(new Data());
    }
    return (List<T>) dataList;
}

无法解析方法“thenReturn(java.util.List)”。这是我按照上述方式调用该方法时收到的错误。

如果 Java 8 中的类型推断得到了改进,有人可以解释为什么我会收到此错误吗?

被调用的方法:

/**
 * Generic method to fetch data from rest endpoint.
 *
 * @param offset       Default should be 0, recursive call in place would increase it till we have fetched all the records.
 * @param dataList     List to be returned and passed on to the recursive call.
 * @param postFixUrl   End point to be used.
 * @param responseType Used to convert the response into json, need this so that we will know the generic type at compile time.
 * @param <T>          Entity for which we are fetching the data.
 * @param arguments    Arguments to be passed to the uri.
 * @return A list of T derived from the response.
 */
public <T> List<T> getDataFromEndpoint(
    int offset, List<T> dataList, String postFixUrl,
    TypeToken<ArrayList<T>> responseType, String arguments)

临时修复以解决该问题,是否有更好的方法来做到这一点。

@Test
public void getDataTest() {
    when(dataSetDao.getDataSetList()).thenReturn(getMockDataSetList());
    when(serviceUtil.getDataFromEndpoint(anyInt(), anyList(), anyString(), any(TypeToken.class), anyString())).thenReturn(getMockDataList(Data.class));
    List<Data> dataList = noaaDataService.getData();
    verify(serviceUtil, times(11)).getDataFromEndpoint(anyInt(), anyList(), anyString(), any(TypeToken.class), anyString());
    assertEquals(11, dataList.size());

}

private <T> List<T> getMockDataList(T type) {
    List<Data> dataList = new ArrayList<>();
    for (int i = 0; i < 1; ++i) {
        dataList.add(new Data());
    }
    return (List<T>) dataList;
}

提前致谢。

最佳答案

问题是你的getDataFromEndpoint(...)方法的返回类型和 T 是通用的类型参数仅根据通过提供传入的方法参数的返回类型推断

<T> T Mockito.any(Class<T> type)

当您传入类文字时 TypeToken.class只有Class<TypeToken> ,而不是所需的类型 Class<TypeToken<Data>> .

因此,serviceUtil.getDataFromEndpoint(...) 的推断类型将是List<Object> ,而不是所需的 List<Data> 。因此,您的下一步将失败,因为返回的推断类型

when(...)

将会

OngoingStubbing<List<Object>>

而不是所需的

OngoingStubbing<List<Data>>

并且只接受 List<Object> ,而不是List<Data> ,如List<Data>不是 List<Object> 的子类型.

解决方案是为通用 serviceUtil.getDataFromEndpoint(...) 提供类型见证。形式为

serviceUtil.<Data> getDataFromEndpoint(...)

并且您的代码应该可以使用所有主要编译器进行编译,无论是 JDK、Eclipse、IntelliJ IDEA 还是 Netbeans。 Generalized target-type inference通常效果很好,但在这种情况下,您为其提供了错误的参数。

关于java - 需要解释 : Generic friendliness to avoid casting, 这在 Java 8 中不再需要,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48136013/

相关文章:

java - Hibernate 5 警告,如何解决这些问题?

c++ - 具有通用模板化基类型的 STL 容器,接受派生类型

c# - 使用 C# 3.0,如何使用泛型集合编写基于接口(interface)的代码?

Java 启动画面比例因子

java - 在流中创建新对象并使用 setter

java - 下载的项目中eclipse中的/src文件夹为空

java - 对对象 HashMap 进行排序(不按键)

swift - 有没有比这更好的方法在 Swift 中进行依赖注入(inject)?

java - Google App Engine 的 JRE 不支持 GWT 和 LocalDate

java - StringJoiner 从每行的第一个位置删除定界符