【问题标题】:Does Java fail to deduce the generic type parameter when using the ternary operator (`?`)?Java在使用三元运算符(`?`)时是否无法推断出泛型类型参数?
【发布时间】:2013-07-08 09:08:20
【问题描述】:

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

我有一个关于编译器能够推断出泛型类型的问题 参数在“直接”分配的情况下,但在三元的情况下失败 运营商 (?)。我的示例使用 Guava 的 Optional 类来说明我的观点,但是 我认为根本问题是一般性的,不限于Optional

Optional 有一个通用函数absent()

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

我可以将Optional&lt;T&gt; 分配给Optional&lt;Double&gt;

// 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&lt;capture#1-of ? extends Object&gt; 转换为 Optional&lt;Integer&gt;

为什么“直接”赋值和使用三元赋值有区别 操作员?还是我还缺少其他东西?

【问题讨论】:

  • of方法的返回类型是什么?
  • absent():public static &lt;T&gt; Optional&lt;T&gt; of(T reference);
  • 你用哪个版本的 javac 编译这个?
  • Java 版本为 Java 1.7。

标签: java generics


【解决方案1】:

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

您也可以查看此bug report 了解更多信息。您可以查看JLS

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

JLS 是这样说的:

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

【讨论】:

    【解决方案2】:

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

    基本上我认为你写的是:

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

    第二行的转换是问题。

    【讨论】:

      猜你喜欢
      • 2014-08-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多