最初,我有这段生产代码:
interface ActionSequence {
public List<Actions> getActions();
我测试了实现该接口的类,如下所示:
assertThat(sequenceUnderTest.getActions(), is(Arrays.asList(action1, action2));
然后我认为将生产界面更改为:
可能是有益的public List<? extends Action> getActions() {
(允许我返回Action的子类列表)。
但是现在eclipse告诉我:
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()
(而不是保留通配符)...然后一切正常。但为什么呢?
答案 0 :(得分:2)
Arrays.asList(action1, action2)
将返回List<Action>
。
因此,is(Arrays.asList(action1, action2))
将返回Matcher<List<Action>>
。
断言具有以下签名:
assertThat(T actual, Matcher<T> matcher)
所以断言在你的情况下需要以下参数:
assertThat(List<Action>, Matcher<List<Action>>)
但你的第一个参数是List<? extends Action>
List<Action>
与List<? extends Action>
完全不同。
例如,您不能将Action元素放入List<SomeSubClassOfAction>
。
这就是为什么这不起作用的原因。
有关详细信息,请参阅Angelika Langer的优秀网站:http://www.angelikalanger.com/GenericsFAQ/FAQSections/Index.html
答案 1 :(得分:1)
你的问题是,为什么
@Override
public List<SomeSubClassOfAction> getActions()
是
的合法实施public List<? extends Action> getActions()
答案是协变回报。由于允许Java1.5子类专门化返回继承的方法。
但我不建议在返回参数中使用通配符类型,因为它不是客户端友好的。请参阅Generic wildcard types should not be used in return parameters及其来自 Effective Java
的引用