Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hamcrest CombinableMatcher - Generic Method won't compile

Tags:

java

generics

I've just been looking at the 'both' and 'and' methods on the org.hamcrest.core.CombinableMatcher in hamcrest 1.2

For some reason, I can't get the following to compile

@Test
public void testBoth() {
    String HELLO = "hello";
    String THERE = "there";
    assertThat("hello there", both(containsString(HELLO)).and(containsString(THERE)));
}

The compilation message I get is

and(org.hamcrest.Matcher<? super java.lang.Object>) in org.hamcrest.core.CombinableMatcher<java.lang.Object> cannot be applied to (org.hamcrest.Matcher<java.lang.String>)

If i specify the type parameter explicity for the method, it works

@Test
public void testBoth() {
    String HELLO = "hello";
    String THERE = "there";
    Assert.assertThat("hello there", CombinableMatcher.<String>
        both(containsString(HELLO)).and(containsString(THERE)));
}

Although this is not nearly as nice.

Can anyone tell me why the compiler can't figure out the types here? I can't believe this is the expected behaviour in this case.

Thanks!

like image 438
ksc0pe Avatar asked Feb 04 '12 04:02

ksc0pe


2 Answers

The compiler should infer LHS <: String (§15.12.2.7 (A) then (B)) from which of course it can trivially deduce LHS = String. JDK 7 honors the spec (and you can specify the source and target as 5 as in javac -source 5 -target).

like image 113
Ben Schulz Avatar answered Oct 19 '22 20:10

Ben Schulz


I hit a similar compile error (while using java 1.8 and hamcrest 1.3) because my first matcher was nullValue() which returns type Object.

assertThat(BigDecimal.ONE, 
    is(both(not(nullValue()))
        .and(not(comparesEqualTo(BigDecimal.ZERO)))));
         ^---The method and(Matcher<? super Object>) in the type 
             CombinableMatcher.CombinableBothMatcher<Object> is not
             applicable for the arguments (Matcher<BigDecimal>)

If you use nullValue(BigDecimal.class), it will compile.

assertThat(BigDecimal.ONE, 
    is(both(not(nullValue(BigDecimal.class)))
        .and(not(comparesEqualTo(BigDecimal.ZERO)))));
like image 2
Jeff Avatar answered Oct 19 '22 22:10

Jeff