Java 8 – 将Integer转换为长编译问题

我的项目中有以下抽象通用数据持有者(简化):

public abstract static class Value { E value; public void setValue(E value) { this.value = value; } public E getValue() { return this.value; } public String toString() { return "[" + value + "]"; } } 

与包含Objects列表的InputCollection一起:

 public static class InputCollection { private ArrayList values; public InputCollection() { this.values = new ArrayList(); } public void addValue(Value value) { System.out.println("addding " + value + " to collection"); this.values.add(value); } public  D getValue(Value value, D defaultValue) { int index = this.values.indexOf(value); if (index == -1) return defaultValue; Object val = this.values.get(index); if (val == null) { return defaultValue; } return ((Value)val).getValue(); } } 

这背后的想法是能够定义一组final变量,在所谓的“状态”中实现这个abstract Value ,如下所示:

 public static final class Input extends Value { public static final Input STRING_ONE = new Input(); public static final Input INTEGER_ONE = new Input(); } 

然后,将这些变量添加到InputCollection的实例中,而InputCollection又由许多“状态”或“进程”共享。 然后可以通过不同的状态更改Input的值,然后在原始状态需要时检索它。 一种共享内存模型。

这个概念已经运行了很多年(是的,这是遗留的),但我们最近开始转向Java 8,这创建了编译错误,即使实现在Java 7上工作。

将以下main添加到上面的代码示例中:

 public static void main (String [] args) { InputCollection collection = new InputCollection(); //Add input to collection collection.addValue(Input.STRING_ONE); collection.addValue(Input.INTEGER_ONE); //At some later stage the values are set Input.INTEGER_ONE.setValue(1); Input.STRING_ONE.setValue("one"); //Original values are then accessed later long longValue = collection.getValue(Input.INTEGER_ONE, -1); if (longValue == -1) { System.out.println("Error: input not set"); } else { System.out.println("Input is: " + longValue); } } 

如果eclipse中的Compiler Compliance级别设置为1.7,则没有编译问题,输出将正确:

 addding [null] to collection addding [null] to collection Input is: 1 

但如果设置为1.8编译错误Type mismatch: cannot convert from Integer to longType mismatch: cannot convert from Integer to long

 long longValue = collection.getValue(Input.INTEGER_ONE, -1); 

但是,如果我访问这个值:

 long longVal = Input.INTEGER_ONE.getValue(); 

没有编译问题,这令人困惑。

它可以通过强制转换来解决,但这在整个项目中都会使用,并且需要进行相当多的强制性测试才能更改每次出现。

Java 8中需要演员的变化是什么? 编译是否变得更加严格? 如果值是直接访问而不是通过集合,编译器为什么不抱怨呢?

我读了如何在Java中从int转换为Long? 并将整数转换为Long ,但并没有真正得到满意的答案。

根据Java 8的JLS,这不应该发生:

5.1.2。 扩大原始转换

对原始类型的19个特定转换称为扩展原始转换:

[..]

  • int到long,float或double

[..]

5.1.8。 拆箱转换

[..]

  • 从类型Integer到int类型

应该发生的是从Integerint的拆箱,然后是对long的扩展转换。 这实际上正如Oracle JDK(1.8.0.25)中所期望的那样发生。

我相信你在JDK中遇到了一个编译器错误。 您应该尝试更新版本或向维护者提交错误。

一个已知的Eclipse bug: https : //bugs.eclipse.org/bugs/show_bug.cgi?id = 440019

在Eclipse 4.5 M3中修复。