在使用三元运算符(`?`)时,Java是否无法推导出泛型类型参数?

时间:2013-07-08 09:08:20

标签: java generics

为什么编译器能够确定一个的泛型类型参数 赋值,但不适用于三元运算符(?)?

我有一个关于编译器能够推断出泛型类型的问题 在“直接”分配的情况下的参数但在三元的情况下失败 运算符(?)。我的例子使用了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>

为什么“直接”分配和使用三元组之间存在差异 运营商?或者还有其他我想念的东西?

2 个答案:

答案 0 :(得分:9)

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

您还可以查看此bug report以获取更多信息。您可以查看JLS

  

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

这是JLS所说的内容:

  

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

答案 1 :(得分:5)

问题是将ternery操作员的结果分配给o2。 编译器无法在多个操作中推断出类型。

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

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

第二行的转换是问题。