Java 8 - 将整数转换为长编译问题

标签 java eclipse generics java-8 long-integer

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

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> 的值然后可以由不同的状态更改,然后在需要时由原始状态检索。一种共享内存模型。

这个概念多年来一直运行良好(是的,这是遗留问题),但我们最近开始转向 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在线

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

但是如果我这样做访问值:

long longVal = Input.INTEGER_ONE.getValue();

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

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

Java 8 中有哪些需要转换的变化?编译以某种方式变得更严格了吗?如果直接访问值而不是通过集合访问,为什么编译器不报错?

我读了 How do I convert from int to Long in Java?Converting Integer to Long ,但我的问题并没有真正得到令人满意的答案。

最佳答案

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

5.1.2. Widening Primitive Conversion

19 specific conversions on primitive types are called the widening primitive conversions:

[..]

  • int to long, float, or double

[..]

5.1.8. Unboxing Conversion

[..]

  • From type Integer to type int

应该发生的是从 Integerint 的拆箱,然后扩大到 long 的转换。这实际上在 Oracle JDK (1.8.0.25) 中按预期发生。

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

关于Java 8 - 将整数转换为长编译问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27105299/

相关文章:

java - tomcat 中用于表单例份验证的领域配置

java - 为什么返回语句中的后增量运算符的行为与 Eclipse 中的预期不同?

c# - 测试通用类

c# - 从继承具体类对抽象类的类型推断

generics - 将通用数字参数与常量进行比较

java - 如何加载正确的语言(在配置中设置)而不是数组中最后的语言

java - Android 应用程序在 Intent 时崩溃

Java · 使用 lambda 对原始矩阵进行装箱和拆箱

android - R.java 中的引用不是最终版本

java - Maven 包括旧版本的依赖项