Примечание: Я нашел несколько вопросов, указывающих различия между javac
и компилятором Eclipse, но насколько я мог видеть, все они обсуждают другие проблемы.Generics и lambdas - различное поведение в javac и компиляторе Eclipse
Предположим, у нас есть этот метод:
public static <T, U> void foo(Supplier<T> a, Function<T, U> b, Consumer<U> c)
{
c.accept(b.apply(a.get()));
}
я нашел различное поведение между javac
и компилятор Eclipse, Java при компиляции вызовов этого метода, и я не уверен, какой из этих двух прав.
Простое использование этого метода может быть:
// variant 1
foo(
() -> Optional.of("foo"),
value -> value.get(),
value -> System.out.println(value));
Компилятор должен быть способен связываться с T
Optional<String>
, используя первый аргумент и U
к String
с помощью второй. Поэтому этот звонок должен быть действительным (на мой взгляд).
Это нормально компилируется с помощью javac
, но не для компиляции с помощью Eclipse:
Несоответствие типа: не удается преобразовать из пустоты в < неизвестной >
Добавление аргумент типа первого аргумента (() -> Optional.<String> of("foo")
) делает его компиляцией в Eclipse тоже.
Вопрос: С точки зрения спецификации Eclipse правильно отклоняет этот вызов (и почему (не))?
Теперь предположим, что мы хотим, чтобы бросить пользовательский (выполнения) исключение, если Optional
пуст:
// variant 2
foo(
() -> Optional.of("foo"),
value -> value.orElseThrow(() -> new RuntimeException()),
value -> System.out.println(value));
Это отвергается как, javac
и компилятор Eclipse,, но с различными сообщениями об ошибках :
javac
: "незарегистрированные исключением X, должны быть пойманы или объявленный быть выброшен"- Eclipse, компилятор: «Несоответствие типов: невозможно преобразовать из пустоты в < неизвестно >»
Когда я добавить аргумент типа к первому аргументу, как указано выше, Eclipse преуспевает в компиляции, а javac
до сих пор не удается. Когда я добавляю <RuntimeException>
как аргумент типа ко второму аргументу, это наоборот, Eclipse терпит неудачу и javac
преуспевает.
Вопрос: Опять же, компиляторы правильно отклоняют этот вызов и почему?
По моему мнению оба варианта должны компилироваться без дополнительных подсказок с использованием аргументов типа. Если это так, я заполню один отчет об ошибке для javac
(относительно «незарегистрированного исключения») и один для компилятора Eclipse (относительно «несоответствия типа»). Но сначала я хочу быть уверенным, что спецификация разделяет мою точку зрения.
Версии, используемые:
javac
: 1.8.0_66- Eclipse, JDT: 3.11.1.v20151118-1100
EDIT:
Я заполнил bug 482781 для выпуска в Eclipse.
Вопрос с javac
уже представлен как JDK-8056983, см. Tunakis answer.
Заблудился бы затмение, если у вас возникли сомнения. Тип вывода очень сложный, весь синтаксис лямбда все еще совершенно новый. У Eclipse исправлено несколько ошибок, но некоторые остались в текущей версии, связанные с такими крайними случаями. – zapl
Eclipse Mars ECJ компилятор действительно багги по сравнению с последней Luna, когда речь заходит об общем расширении. Я уже столкнулся с по меньшей мере тремя случаями, когда ECJ 3.11 терпит неудачу или даже застревает в бесконечном цикле, в то время как javac и ECJ 3.10 скомпилированы правильно. Вот почему я все еще использую Луну. –
Ошибка Eclipse уже исправлена для 4.6 M1 через https://bugs.eclipse.org/470826, которая также запланирована для обратного порта на марс. 2 –