泛型:如何处理类层次结构

时间:2017-04-13 14:57:41

标签: java generics

我有一个存储库,它返回实现两个接口的对象

public interface MyRepository<T extends A & B> extends JpaRepository<T, Long>
  List<T> findAll();
  ...

使用Spring我将这些实现注入另一个类,但另外指定泛型类型本身应另外实现某个接口C

class X {
  @Autowired
  private List<MyRepository<? extends C> myCRepos;

请注意,C是一个不扩展A&amp; A的界面。 B,但我想要注入的所有具体实现都实现了所有三个接口

class MyConcreteClass implements A, B, C

所以Spring正确找到了public interface ConcreteRepo extends MyRepository<MyConcreteClass>,并按照ListX中的预期进行了注释。

如果我现在使用findAll方法,则IDE会将其返回类型推断为List<? extends C>

为什么返回类型不是List<? extends A & B & C>

为了测试我想模拟这个findAll,所以返回一个正确类型的对象,但是下面的代码已经失败了:

List<? extends C> someTestList = new ArrayList<>();
someTestList.add(new MyConcreteClass()); // 
// has error like
// The method add(capture#1-of ? extends C) in the type 
// List<capture#1-of ? extends C> is not applicable for the arguments (C)

我该如何解决此错误?

最后,我想嘲笑整件事

Mockito.when(myRepo.findAll()).thenReturn(someTestList);

同样的问题,someTestList类型应该是什么以及如何创建它?

2 个答案:

答案 0 :(得分:1)

我不确定第一个问题的答案,但第二个问题与您的复杂类型层次结构无关。每当你有List<? extends Something>时,你将无法向它添加内容,因为这基本上将列表声明为“某种未知类型”的列表,而Java无法确保MyConcreteClass是一个实例“某种未知类型”。您可以将someTestList声明为List<MyConcreteClass>

来解决此问题和第三个问题

答案 1 :(得分:0)

在更多关于泛型的阅读之后,这就是解决方案。首先,正如Philipp Wendler所指出的,someTestList必须在没有通配符的情况下输入,才能真正输入内容。

List<C> someTestList = new ArrayList<>();
someTestList.add(new MyConcreteClass()); // 

此外,在调用Mockito时,编译器需要提示返回类型:

Mockito.<List<? extends C>>when(myRepo.findAll()).thenReturn(someTestList);