所以,让我们有一个字符串列表和一个函数,它接受一个 Hamcrest 匹配器并返回matches()
提供的匹配器方法的结果:
public boolean matchIt(final Matcher<? super List<String>> matcher) {
final List<String> lst = obtainListFromSomewhere();
return matcher.matches(lst);
}
到目前为止,一切都很好。现在我可以轻松调用:
matchIt(empty());
matchIt(anything());
matchIt(hasItem("item"));
matchIt(everyItem(equalToIgnoringCase("item")));
...因为所有这些工厂静态方法都会生成适合方法签名的匹配器Matcher<? super List<String>>
。
但是,我相信接受 Iterable 对象的匹配器也应该被该matchIt()
方法接受:
matchIt(everyItem(anything()));
所以我天真地改变了matchIt()
方法签名:
public boolean matchIt(final Matcher<? super List<? super String>> matcher);
但它根本不起作用。不仅不接受everyItem(anything())
,甚至不接受之前正确的everyItem(equalToIgnoringCase("item"))
说法(1.7.0_05编译器版本):
actual argument Matcher<Iterable<String>> cannot be converted to Matcher<? super List<? super String>> by method invocation conversion
什么?那么这里有什么问题呢?是matchIt()
方法签名还是everyItem()
Hamcrest 签名设计错误?还是只是 Java 泛型系统无法修复?非常感谢您的评论!
编辑@rlegendi 我的目的是为客户端提供一个接口,以添加和执行关于列表的谓词。这就是matchIt()
方法。在这种情况下调用matchIt(anything())
是有意义的,客户端想知道列表是否是任何东西。调用matchIt(empty())
意味着客户端想知道列表是否为空。反之亦然。matchIt(everyItem(equalToIgnoringCase("item")))
_matchIt(hasItem("item"))
我的目标是尽可能获得最佳 matchIt()
方法签名。对于Matcher<? super List<String>>
之前的所有场景都可以正常工作。但是,我相信客户端也应该被允许添加Matcher<Iterable<Object>>
匹配器(例如matchIt(everyItem(notNullValue())
,这里非常有意义,客户端想知道列表中的每个 String 项是否不为空)。
但是我找不到正确的签名,matchIt(Matcher<? super List<? super String>>)
不适用于everyItem(notNullValue());
我使用 Hamcrest 1.3。
编辑2:
我相信我已经找到了我的根本误解。
该everyItem(anything())
表达式返回一个类型为 的对象Matcher<Iterable<Object>>
。所以我可以轻松做到Matcher<Iterable<Object>> m = everyItem(anything());
但是我不明白为什么我不能这样做Matcher<? super List<? super String>> m1 = m;
。似乎Matcher<Iterable<Object>>
不是Matcher<? super List<? super String>>
,但我不明白为什么。
我什至做不到Matcher<? super List<?>> m1 = m;
。Matcher<Iterable<Object>>
不是Matcher<? super List<?>>
吗?为什么?