Java 8 - 将整数转换为长编译问题 [英] Java 8 - converting an Integer to a long compilation issue

查看:146
本文介绍了Java 8 - 将整数转换为长编译问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  public abstract static class Value& {

E值;

public void setValue(E value){
this.value = value;
}

public E getValue(){
return this.value;
}

public String toString(){
return[+ value +];
}
}

随着 InputCollection 其中包含对象的列表:

  public static class InputCollection {

private ArrayList< Object>值;

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;

对象val = this.values.get(index);
if(val == null){
return defaultValue;
}

return((Value< D>)val).getValue();
}
}

这背后的想法是能够定义一个最终变量实现这个抽象 值< E> 所谓'状态',如下所示:

  public static final class Input< E>扩展值< E> {
public static final Input< String> STRING_ONE = new Input< String>();
public static final Input< Integer> INTEGER_ONE = new Input< Integer>();
}

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



这个概念已经运行好几年(是的,这是遗产),但是我们最近开始转移到Java 8,而这个创建编译错误,即使实现在Java 7上工作。



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

  public static void main(String [] args){

InputCollection collection = new InputCollection );
//添加收藏
collection.addValue(Input.STRING_ONE);
collection.addValue(Input.INTEGER_ONE);

//在稍后的阶段,值为
Input.INTEGER_ONE.setValue(1);
Input.STRING_ONE.setValue(one);

//然后再访问原始值
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]收集
addding [ null]收集
输入是:1

但如果设置为1.8编译错误类型不匹配:无法从Integer转换为长

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

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

  long longVal = Input.INTEGER_ONE.getValue(); 

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



它可以用一个演员解决,但这在整个项目中都使用,需要相当多的强制性测试才能更改每一次事件。



什么在Java 8中需要转换?汇编越来越严格吗?为什么编译器不会呻吟,如果值是直接访问,而不是通过集合?



我读
如何在Java中将int转换为Long?

将整数转换为长格式,但并没有真正让我满意的答案我的问题。根据 JLS for Java 8 这不应该发生:


5.1.2 。扩大原始转换



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



$ [$]


  • int long,float或double



[..]



5.1.8。卸载转换



[..]




  • 从类型整数键入int


应该发生什么是从 Integer int ,然后扩大转换为 long 。这实际上是在Oracle JDK(1.8.0.25)中预期的发生。



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


I have the following abstract generic data holder in my project (simplified):

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

Along with an InputCollection which contains a list of 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();
    }
}

The idea behind this is to be able to define a set of final variables which implements this abstract Value<E> in a so-called 'state', like so:

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>();
}

Then, adding these variables to an instance of InputCollection, which in turn is shared by many 'states' or 'processes'. The value of an Input<E> can then be changed by a different state, and then be retrieved when needed by the original state. A kind of shared memory model.

This concept has been working fine for years (yea, this is legacy), but we recently started moving over to Java 8, and this created compilation errors, even though the implementation worked on Java 7.

Add the following main to the above code samples:

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);
    }
}

If the Compiler Compliance level in eclipse is set to 1.7, there is no compilation issues, and the output will correctly be:

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

but if it is set to 1.8 compilation error Type mismatch: cannot convert from Integer to long on the line

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

But if I access the value doing this:

long longVal = Input.INTEGER_ONE.getValue();

there are no compilation issues, which is confusing.

It can be solved with a cast, but this is used all over the project and would require quite a bit of mandatory testing to change every occurrence.

What changed in Java 8 that requires the cast? Did compilation get stricter somehow? And why does the compiler not moan if the value is access directly and not through the collection?

I read How do I convert from int to Long in Java? and Converting Integer to Long , but didn't really get satisfying answers to my question.

解决方案

According to the JLS for Java 8 this should not happen:

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

What should happen is an unboxing from Integer to int, and then a widening conversion to long. This is actually happening as expected in Oracle JDK (1.8.0.25).

I believe you came across a compiler bug into your JDK. You should probably try an updated version or file a bug with the maintainers.

这篇关于Java 8 - 将整数转换为长编译问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆