Во время миграции нашей кодовой базы с java 1.7 на 1.8 мы получили сообщение об ошибке «Метод... неприменим для аргументов» в нескольких местах кода, все они следуют одному и тому же шаблону использования дженериков.
В настоящее время мы используем в основном Eclipse Mars
(4.5.2) на Windows 7
, но можем подтвердить поведение и с Neon
(4.6). И Javac
, и ecj
с уровнем соответствия 1.7 могут скомпилировать наш код без ошибок.
Вот минимальный, полный и проверяемый пример:
public class ComplexInterfaceTest {
public static class Foo {}
public interface Bar {
void print();
}
public static class SubFooBar extends Foo implements Bar {
public void print() {
System.out.println(this.getClass().getSimpleName());
}
}
public static class FooBar<T extends Foo & Bar> {
public static <T extends Foo & Bar> FooBar<T> makeFooBar() {
return new FooBar<>();
}
public void create(T value) {
value.print();
return;
}
}
public static class Base<T extends Foo> {}
public static class Subclass extends Base<SubFooBar> {
public void doSomething(SubFooBar value) {
// FooBar.<SubFooBar>makeFooBar().create(value);
FooBar.makeFooBar().create(value);
}
}
public static void main(String[] args) {
new Subclass().doSomething(new SubFooBar());
}
}
Теперь переключение закомментированных строк в методе doSomething
приводит к компиляции кода, поэтому у нас есть обходной путь. Тем не менее сообщение об ошибке кажется неправильным, поскольку класс SubFooBar
расширяет Foo
и реализует Bar
, поэтому он выполняет контракт <T extends Foo & Bar>
, который требуется в <T extends Foo & Bar> FooBar<T> makeFooBar()
, поэтому на самом деле T
IMO должен быть привязан к SubFooBar
.
Я искал похожие вопросы и нашел следующие: Различия в выводе типов JDK8 javac/ Eclipse Luna? Тип Ошибка компилятора вывода в Eclipse с Java8, но не с Java7
Это заставляет меня думать, что это может быть ошибка ecj
. В этом курсе я тоже смотрел Eclipse Bugzilla
но ничего похожего не нашел, видел вот эти:
- 430686 проверено исправлено - у меня нет
- 440019 имеет отношение к скалярному типу - мой нет
- 492838, 448793 имеют отношение к подстановочным знакам – мой нет
Теперь Eclipse Bugzilla
дискуссии полны подробностей о внутренней работе ecj
, за которыми я не всегда могу уследить. Что я понимаю, так это общее мнение, что компилятор Eclipse
должен строго следовать JLS
, а не javac
(в тех случаях, когда это неправильно), поэтому это не обязательно должна быть ошибка в ecj
. Если бы это не было ошибкой ecj
, то компиляция кода должна была бы быть ошибкой javac
.
Что меня интересует, так это - для тех, кто может проанализировать процесс вывода типа моего фрагмента кода - должен ли код скомпилироваться или я допустил ошибку при кодировании?
ИЗМЕНИТЬ
Как я и обещал опубликовать результаты моего отчета в Eclipse Bugzilla
: дефект имеет идентификатор № 497905 (Стефан Херрманн разместил ссылку в своем комментарии под принятым ответом) и в настоящее время предназначен для версии 4.7.