java – Hamcrest匹配器的冲突重载

匹配器 IsIterableContainingInAnyOrder对静态工厂方法containsInAnyOrder有两个重载(两者都有返回类型Matcher< java.lang.Iterable<?extends T>>):

> containsInAnyOrder(java.util.Collection< Matcher<?super T>> itemMatchers)
> containsInAnyOrder(Matcher<?super T> … itemMatchers)

现在考虑以下程序:

import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.junit.Assert.assertThat;

import java.util.Arrays;

import org.junit.Test;

public class SomeTest {

    @SuppressWarnings("unchecked")
    @Test
    public void foo() {
        assertThat(Arrays.asList("foo","bar"),containsInAnyOrder(equalTo("foo"),equalTo("bar")));
    }

}

当它作为JUnit测试执行时,它会按预期传递.它使用上面显示的containsInAnyOrder的第二个重载.

现在,当我将断言更改为此时(与documentation of the first overload中给出的示例完全匹配):

assertThat(Arrays.asList("foo",containsInAnyOrder(Arrays.asList(equalTo("foo"),equalTo("bar"))));
                              ^^^^^^^^^^^^^^

它不再编译,因为现在编译器推断出containsInAnyOrder的返回类型

Matcher<Iterable<? extends List<Matcher<String>>>>

似乎编译器仍然选择第二个重载.如果它使用第一个,示例应该有效.为什么它会像这样?我怎样才能做到这一点?

我使用的是Hamcrest 1.3和Oracle Java 1.7.

解决方法

它实际上匹配两个重载方法.我不确定为什么选择第一个,但你可以提供一个提示,让它选择正确的方法.

通过将参数强制转换为Collection:

assertThat(Arrays.asList("foo",containsInAnyOrder((Collection)Arrays.asList(equalTo("foo"),equalTo("bar"))));

或者将泛型类型T指定为< String> (但不能使用静态导入):

assertThat(Arrays.asList("foo",IsIterableContainingInAnyOrder.<String>containsInAnyOrder(Arrays.asList(equalTo("foo"),equalTo("bar"))));

相关文章

Java中的String是不可变对象 在面向对象及函数编程语言中,不...
String, StringBuffer 和 StringBuilder 可变性 String不可变...
序列化:把对象转换为字节序列的过程称为对象的序列化. 反序...
先说结论,是对象!可以继续往下看 数组是不是对象 什么是对...
为什么浮点数 float 或 double 运算的时候会有精度丢失的风险...
面试题引入 这里引申出一个经典问题,看下面代码 Integer a ...