Подтвердить что ты не робот

Не удается ли Java вывести параметр типового типа при использовании тернарного оператора (`?`)?

Почему компилятор может определить параметр родового типа для но не для тернарного оператора (?)?

У меня вопрос о том, что компилятор способен вывести общий тип параметр в случае "прямого" назначения, но в случае тройного оператора (?). В моих примерах используется класс Guava Optional, чтобы указать, но Я думаю, что основная проблема является общей и не ограничивается Optional.

Optional имеет общую функцию absent():

public static <T> Optional<T> absent();

и я могу назначить Optional<T> для Optional<Double>:

// no compiler error
final Optional<Double> o1 = Optional.absent();

Как компилятор понимает, что T должен быть Double в этом случае. Потому как при использовании тернарного оператора (?) мне нужно сообщить компилятору конкретно нам Integer как общий параметр

// Type mismatch: cannot convert from Optional<capture#1-of ? extends Object> to Optional<Integer>
final Optional<Integer> o2 = true
    ? Optional.of(42)
    : Optional.<Integer>absent();

в противном случае я получаю следующую ошибку

Несоответствие типов: невозможно преобразовать из Optional<capture#1-of ? extends Object> в Optional<Integer>

Почему существует разница между "прямым" назначением и использованием тройной оператор? Или есть что-то еще, что мне не хватает?

4b9b3361

Ответ 1

Из-за правил вывода типа, кажется, что тернарное выражение не выводит параметр типа из возвращаемого типа. Тип тройного выражения зависит от типов его операндов. Но один из операндов имеет неопределенный параметр типа (Optional.absent()). В этот момент тернарное выражение все еще не имеет типа, поэтому оно не может влиять на параметр типа.

Дополнительную информацию можно найти в этом отчете об ошибке. Вы можете посмотреть JLS.

Тип условного выражения является результатом применения преобразования захвата (5.1.10) в lub (T1, T2)

Вот что JLS говорит:

Если результат метода встречается в контексте, где он будет подвергнут преобразованию присваивания типу S, то пусть R - объявленный тип результата метода, и пусть R '= R [T1 = B (T1)... Tn = B (Tn)], где B (Ti) является типом, выведенным для Ti в предыдущем разделе, или Ti, если не было принято никакого типа.

Ответ 2

Проблема заключается в том, что результат оператора ternery присваивается o2. Компилятор не может выводить тип для нескольких операций.

В принципе, я думаю, вы пишете короткую форму:

Optional<?> tmp = true ? Optional.of(42): Optional.absent();
final Optional<Integer> o2 = tmp;

Преобразование второй строки является проблемой.