2014-11-24 47 views
11

我已经在我的项目下列抽象通用数据持有者(简体):的Java 8 - 一个整数转换为长编译问题

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 + "]"; 
    } 
} 

随着它包含的Objects列表的InputCollection

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变量,将实现该abstractValue<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编译器的级别被设置为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,但并没有真正得到满意的回答我的问题。

+1

你可以试试用'javac'编译这个吗?我也有这个问题,我相信这是一个日食错误。如果我在代码中添加了演员表,它会发出“不必要的演员表”警告..​​.... :) – 2014-11-24 13:34:18

+0

我无法在我的机器上进行复制。在Java8中,它完全可以工作。 – Jatin 2014-11-24 13:40:30

+2

这实际上是Eclipse内部编译器中的一个错误。注意:Eclipse不使用来自安装的JDK的'javac'命令,但使用内部编译器。该编译器报告错误。使用JDK工具编译它工作得很好。 – Seelenvirtuose 2014-11-24 13:41:49

回答

7

按照JLS for Java 8这不应该发生:

5.1.2。加宽原语转换上的原始类型

19个特定的转换被称为宽元数据的转换:

[..]

  • INT到长整型,浮点,或双

[..]

5.1.8。取消装箱转换

[..]

  • 从类型整数为int类型

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

我相信你在你的JDK中遇到了一个编译器错误。您应该尝试更新的版本或向维护人员报告错误。

+1

你说得对。从JDK使用'javac'工作得很好。它似乎是Eclipse编译器中的一个错误。 – Seelenvirtuose 2014-11-24 13:42:35

+2

这似乎是在Eclipse Mars 4.5.0中修复的 – Ian2thedv 2015-08-06 09:11:02

6

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

在Eclipse 4.5 M3固定。

+0

希望我有办法在STS 3.6中获得修复。是吗? – jayP 2015-10-15 19:39:11

+0

我不知道。我只是下载了新版本,这很好。但是,是的,我可以想象一个您不想升级(或不能)的设置。尝试联系sts人的某处。 – 2015-10-16 07:05:07