1

最初,我有这段生产代码:

interface ActionSequence {
   public List<Actions> getActions();

我测试了实现该接口的类,如下所示:

assertThat(sequenceUnderTest.getActions(), is(Arrays.asList(action1, action2));

然后我认为将生产界面更改为:

public List<? extends Action> getActions() {

(允许我返回 Action 的子类列表)。

但现在日食告诉我:

The method assertThat(T, Matcher<? super T>) in the type Assert is not applicable for the arguments (List<capture#1-of ? extends Action>, Matcher<List<Action>>)

我想:当我更改实现 ActionInterface的类时

@Override
public List<SomeSubClassOfAction> getActions()

(而不是保留通配符)......然后一切正常。但为什么?

4

2 回答 2

2

Arrays.asList(action1, action2)将返回一个List<Action>. is(Arrays.asList(action1, action2))因此将返回一个Matcher<List<Action>>.

assertThat 具有以下签名:

assertThat(T actual, Matcher<T> matcher)

所以 assertThat 在您的情况下需要以下参数:

assertThat(List<Action>, Matcher<List<Action>>)

但是您的第一个参数是 aList<? extends Action> 并且 a 与 aList<Action>完全不同List<? extends Action>。例如,您不能将 Action 元素放入List<SomeSubClassOfAction>. 这就是为什么这行不通。

详情请看Angelika Langer的优秀网站:http ://www.angelikalanger.com/GenericsFAQ/FAQSections/Index.html

于 2016-01-15T13:30:40.207 回答
1

Your question was, why

@Override
public List<SomeSubClassOfAction> getActions()

is a legal Implementation of

public List<? extends Action> getActions()

The Answer is covariant return. Since Java1.5 subclasses are allowed to specialize the return of inherited methods.

But I wouldn't recommend having wildcard types in return parameters because it isn't client friendly. See Generic wildcard types should not be used in return parameters and its quote from Effective Java

于 2016-01-15T14:02:27.437 回答