泛型地狱:hamcrest matcher作为方法参数
因此,让我们有一个字符串列表和一个函数,该函数采用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>>
但是,我相信接受对象可迭代对象的匹配器也应该被该方法接受:matchIt()
matchIt(everyItem(anything()));
所以我天真地改变了方法签名:matchIt()
public boolean matchIt(final Matcher<? super List<? super String>> matcher);
但它根本不起作用。它不仅不接受,甚至不接受以前正确的说法(1.7.0_05编译器版本):everyItem(anything())
everyItem(equalToIgnoringCase("item"))
actual argument Matcher<Iterable<String>> cannot be converted to Matcher<? super List<? super String>> by method invocation conversion
什么?那么这里出了什么问题呢?是方法签名还是Hamcrest签名设计错误?或者只是Java泛型系统无法修复?非常感谢您的评论!matchIt()
everyItem()
编辑@rlegendi我在这里的目的是为客户端提供一个接口来添加和执行有关列表的谓词。这就是方法。在这种情况下,调用是有意义的,客户端想知道列表是否是任何东西。调用意味着客户端想知道列表是否为空。反之亦然。matchIt()
matchIt(anything())
matchIt(empty())
matchIt(everyItem(equalToIgnoringCase("item")))
matchIt(hasItem("item"))
我的目标是尽可能有一个最好的方法签名。适用于上述所有方案。但是,我认为也应该允许客户端添加匹配器(例如,在这里非常有意义,客户端想知道列表中的每个字符串项是否不为空)。matchIt()
Matcher<? super List<String>>
Matcher<Iterable<Object>>
matchIt(everyItem(notNullValue())
但是我找不到正确的签名,不适用于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<?>>