Следующий простой класс (repo для его воспроизведения):
import static org.hamcrest.*;
import static org.junit.Assert.assertThat;
import java.util.*;
import org.junit.Test;
public class TestGenerics {
@Test
public void thisShouldCompile() {
List<String> myList = Arrays.asList("a", "b", "c");
assertThat("List doesn't contain unexpected elements", myList, not(anyOf(hasItem("d"), hasItem("e"), hasItem("f"))));
}
}
Поведение зависит от версии JDK:
- Правильно компилируется в JDK <= 8 (тестируется с 7 и 8)
- Компиляция не выполняется с использованием JDK 9+ (тестируется с 9, 10 и 11 EA)
Со следующей ошибкой:
[ERROR] /tmp/jdk-issue-generics/src/test/java/org/alostale/issues/generics/TestGenerics.java:[17,17] no suitable method found for assertThat(java.lang.String,java.util.List<java.lang.String>,org.hamcrest.Matcher<java.lang.Iterable<? super java.lang.Object>>)
method org.junit.Assert.<T>assertThat(java.lang.String,T,org.hamcrest.Matcher<? super T>) is not applicable
(inference variable T has incompatible bounds
upper bounds: java.lang.String,java.lang.Object
lower bounds: capture#1 of ? super T?,capture#2 of ? super java.lang.Object,capture#3 of ? super java.lang.Object,java.lang.Object,java.lang.String,capture#4 of ? super T?)
method org.junit.Assert.<T>assertThat(T,org.hamcrest.Matcher<? super T>) is not applicable
(cannot infer type-variable(s) T
(actual and formal argument lists differ in length))
Это ожидаемое изменение в JDK 9 или ошибка?
Таким образом, я мог бы собрать шаблонов для типизированных переменных, и это сработает:
Matcher<Iterable<? super String>> m1 = hasItem("d");
Matcher<Iterable<? super String>> m2 = hasItem("e");
Matcher<Iterable<? super String>> m3 = hasItem("f");
assertThat(myList, not(anyOf(m1, m2, m3)));
Но все же возникает вопрос: правильно ли javac
<= 8 способен выводить типы, но не в 9+?