我的项目中有以下抽象通用数据持有者(简化):
public abstract static class Value<E> {
E value;
public void setValue(E value) {
this.value = value;
}
public E getValue() {
return this.value;
}
public String toString() {
return "[" + value + "]";
}
}
InputCollection
包含Objects
列表:
public static class InputCollection {
private ArrayList<Object> 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> D getValue(Value<D> 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<D>)val).getValue();
}
}
这背后的想法是能够定义一组final
个变量,这些变量在所谓的“状态”中实现这个abstract
Value<E>
,就像这样:
public static final class Input<E> extends Value<E> {
public static final Input<String> STRING_ONE = new Input<String>();
public static final Input<Integer> INTEGER_ONE = new Input<Integer>();
}
然后,将这些变量添加到InputCollection
的实例中,而Input<E>
的实例又由许多州共享&#39;或者&#39;进程&#39;。然后可以通过不同的状态更改main
的值,然后在原始状态需要时检索它。一种共享内存模型。
这个概念多年来一直运行良好(是的,这是遗留的),但我们最近开始转向Java 8,这就产生了编译错误,即使实现在Java 7上有效。
将以下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);
}
}
添加到上面的代码示例中:
addding [null] to collection
addding [null] to collection
Input is: 1
如果eclipse中的Compiler Compliance级别设置为1.7,则没有编译问题,输出将正确:
Type mismatch: cannot convert from Integer to long
但如果在行
上设置为1.8编译错误long longValue = collection.getValue(Input.INTEGER_ONE, -1);
long longVal = Input.INTEGER_ONE.getValue();
但是,如果我访问这个值:
{{1}}
没有编译问题,这令人困惑。
它可以通过强制转换来解决,但这在整个项目中都会被使用,并且需要进行相当多的强制性测试才能更改每次出现。
Java 8中需要演员的变化是什么?编译是否变得更加严格?如果值是直接访问而不是通过集合,编译器为什么不抱怨?
我看了 How do I convert from int to Long in Java? 和 Converting Integer to Long,但我的问题并没有得到令人满意的答案。
答案 0 :(得分:8)
根据JLS for Java 8,这不应该发生:
<强> 5.1.2。扩大原始转换
对原始类型的19个特定转换称为扩展原语转换:
[..]
- int to long,float或double
[..]
<强> 5.1.8。取消装箱转换
[..]
- 从类型Integer到类型int
应该从Integer
到int
进行拆箱,然后扩展转换为long
。这实际上正如Oracle JDK(1.8.0.25)中所期望的那样发生。
我相信您在JDK中遇到了编译器错误。您应该尝试更新版本或向维护者提交错误。
答案 1 :(得分:6)
已知的Eclipse错误:https://bugs.eclipse.org/bugs/show_bug.cgi?id=440019
已在Eclipse 4.5 M3中修复。