我使用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
并将默认行为从警告转为错误。但这也会导致其他不必要的错误。
有没有办法通过日食设置解决这个问题?
这不是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;
是。