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:
- 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. - 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 beClass<? extends Number>. - Which tool should I use to see the types of the implicit lambda? Can I check it with some tool from the JDK?
- 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