17

Why is the compiler able to determine the generic type parameter for an assignment, but not for the ternary operator (?)?

I have a question regarding the compiler being able to deduce the generic type parameter in case of a "direct" assignment but failing in case of the ternary operator (?). My examples uses Guava's Optional class, to make my point, but I think the underlying issue is generic and not restricted to Optional.

Optional has a generic function absent():

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

and I can assign an Optional<T> to an Optional<Double>:

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

How does the compiler realize, that T should be Double in this case. Because when using the ternary operator (?), I need to tell the compiler specifically to us Integer as the generic parameter

// 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();

otherwise I get the following error

Type mismatch: cannot convert from Optional<capture#1-of ? extends Object> to Optional<Integer>

Why is there a difference between a "direct" assignement and using the ternary operator? Or is there something else I am missing?

4

2 回答 2

9

由于类型推断规则,三元表达式似乎不会从返回类型推断类型参数。三元表达式的类型取决于其操作数的类型。但是其中一个操作数具有未确定的类型参数 ( Optional.absent())。此时三元表达式仍然没有类型,因此它不会影响类型参数。

您还可以查看此错误报告以获取更多信息。您可以查看JLS

条件表达式的类型是对 lub(T1, T2) 应用捕获转换 (??5.1.10) 的结果

JLS说的是:

如果方法结果发生在将赋值转换为类型 S 的上下文中,则令 R 为方法的声明结果类型,并令 R' = R[T1 = B(T1) ... Tn = B(Tn)] 其中 B(Ti) 是上一节中为 Ti 推断的类型,如果没有推断出类型,则为 Ti。

于 2013-07-08T09:13:50.607 回答
5

问题是三元运算符的结果分配给了o2。编译器无法跨多个操作推断类型。

基本上我认为你写的简短形式是:

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

第二行的转换是问题所在。

于 2013-07-08T09:16:14.833 回答