三元运算符无法识别Eclipse中的编译错误

问题描述 投票:2回答:1

我使用Eclipse作为IDE并使用下面的代码

List<Long> countList = new ArrayList<>();
Long count = (countList != null && !countList.isEmpty()) ? countList.get(0) : 0;

在Eclipse中,else的自动装箱会产生编译错误,但事实并非如此。我已经尝试了最新的eclipse版本Photon,它仍然是相同的。

但是当我使用Jenkins构建项目时,它会抛出正确的编译错误。有人可以建议,如何解决这个问题?

我尝试了设置Preferences -> Errors/Warnings -> Boxing and unboxing conversions并将默认行为从警告转为错误。但这也会导致其他不必要的错误。

有没有办法通过日食设置解决这个问题?

java eclipse language-lawyer conditional-operator autoboxing
1个回答
3
投票

这不是Eclipse中的错误,而是javac中的错误。它只影响Java 8,因此使用不同的版本可以解决问题。

请注意,虽然规范不允许使用类似Long var = 0;的构造,但条件表达式是完全不同的字段。

Java语言规范的section about the “Conditional Operator ? :有一个数值条件表达式的概念,甚至明确包含一个conversion table,表明Long类型的第二个参数和int类型的第三个参数的组合应该是有效的,结果类型为“bnp(Long,int)”,而“ bnp“代表”Binary Numeric Promotion“¹

¹我故意链接到规范的Java 8版本,这是javac表现出这种错误行为的版本。

简而言之,如果需要,它意味着取消装箱,然后在需要时加宽原始转换,最后,如果需要,结果将再次装箱。

请注意,即使Java 8的javac也能正确执行此操作,只要不涉及通用方法:

Long boxed = !countList.isEmpty()? countList.get(0): null;
Long count = boxed != null? boxed: 0;// promotes int to Long

不会产生编译错误。

在涉及泛型方法时产生编译器错误的行为已在JDK-8162708 Unexpected syntax error with ternary operator and generics methods中描述。它还提到javac确实在Java 7和Java 9下正确处理了这个构造,因此问题只发生在Java 8中。我还刚刚验证了编译器错误没有出现在Java 11和Java 12的当前状态中。

值得指出的是,上述规则可能具有反直觉的行为。例如。

boolean someCondition = true;
Long variable = null;
Long other = someCondition? variable: 0;

将抛出一个NullPointerException,因为存储在variable中的引用未通过,但将被取消装箱并重新装箱。

同样,

Integer variable = 42;
Long other = variable;

不是有效的作业,但是

Integer variable = 42;
Long other = true? variable: 0L;

是。

© www.soinside.com 2019 - 2024. All rights reserved.