Incompatible types error when using implicit lambda

Viewed 416

I'm using java 8 and I have the following test code with JUnit and AssertJ:

@Test
public void test() {
    List<Number> actual = new ArrayList<>();
    actual.add(Double.valueOf(1));
    actual.add(Integer.valueOf(1));
    actual.add(Long.valueOf(1));

    List<Class<? extends Number>> expected = new ArrayList<>();
    expected.add(Double.class);
    expected.add(Integer.class);
    expected.add(Long.class);

    // Just information how IDEA is generating types for the different statements
    ListAssert<? extends Class<? extends Number>> implicitLambda = assertThat(actual).extracting(t -> t.getClass());
    ListAssert<Class<? extends Number>> explicitLambda = assertThat(actual).extracting((Extractor<Number, Class<? extends Number>>) t -> t.getClass());
    ListAssert<Class<?>> methodReference = assertThat(actual).extracting(Number::getClass);

    // Does not compile
    // Error:(31, 84) java: incompatible types: java.util.List<java.lang.Class<? extends java.lang.Number>> cannot be converted to java.lang.Iterable<? extends java.lang.Class<capture#1 of ? extends java.lang.Number>>
    assertThat(actual).extracting(t -> t.getClass()).containsExactlyElementsOf(expected);

    // Compile because of explicit types
    assertThat(actual).extracting((Extractor<Number, Class<? extends Number>>) t -> t.getClass()).containsExactlyElementsOf(expected);

    // Compile, but don't understand why
    assertThat(actual).extracting(Number::getClass).containsExactlyElementsOf(expected);

}

At the first assert I got a compile error:
Error:(31, 84) java: incompatible types: java.util.List<java.lang.Class<? extends java.lang.Number>> cannot be converted to java.lang.Iterable<? extends java.lang.Class<capture#1 of ? extends java.lang.Number>>
I have the following questions:

  1. Is the return type of the lambda in the first assert really <? extends Class<? extends Number>.
    I just rely on the local variables generated by IDEA.
  2. If it is, then why is that? The getClass documentation says that
    The actual result type is Class<? extends |X|> where |X| is the erasure of the static type of the expression on which getClass is called.
    If I understand correctly it should be Class<? extends Number>.
  3. Which tool should I use to see the types of the implicit lambda? Can I check it with some tool from the JDK?
  4. Why is the last assert with method reference compiles? If it really return Class<?>, then I understand, but why the return type different for this and the implicit lambda?

Relevant AssertJ documentations:
AbstractIterableAssert
AbstractIterableAssert.html#extracting
AbstractIterableAssert.html#containsExactlyElementsOf

1 Answers
Related