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 long
行Type 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类型
应该发生的是从Integer
到int
的拆箱,然后是对long
的扩展转换。 这实际上正如Oracle JDK(1.8.0.25)中所期望的那样发生。
我相信你在JDK中遇到了一个编译器错误。 您应该尝试更新版本或向维护者提交错误。
一个已知的Eclipse bug: https : //bugs.eclipse.org/bugs/show_bug.cgi?id = 440019
在Eclipse 4.5 M3中修复。