繁体   English   中英

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

[英]Does Java fail to deduce the generic type parameter when using the ternary operator (`?`)?

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

我有一个问题,关于编译器能够在“直接”赋值的情况下推导出泛型类型参数,但在三元运算符( ? )的情况下失败。 我的例子使用了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<capture#1-of ? extends Object>Optional<Integer>

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

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

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

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

这是JLS所说的:

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

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM