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

Наряду с 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 установлено значение 1.7, проблем с компиляцией не возникает, и результат будет правильно:

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

но если для строки Type mismatch: cannot convert from Integer to long установлена ​​ошибка компиляции 1,8 в строке

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

Но если я получаю доступ к этому значению:

long longVal = Input.INTEGER_ONE.getValue();

нет проблем с компиляцией, что запутывает.

Его можно решить с помощью броска, но он используется по всему проекту и потребует довольно много обязательного тестирования для изменения каждого события.

Что изменилось в Java 8, требующем броска? Разве компиляция стала более строгой? И почему компилятор не стонет, если значение имеет доступ напрямую, а не через коллекцию?

Я читаю Как преобразовать из int в Long в Java? а также Преобразование целого в длинный, но на самом деле не получило удовлетворительных ответов на мой вопрос.

Ответ 1

В соответствии с JLS для Java 8 этого не должно быть:

5.1.2. Расширение примитивного преобразования

19 конкретных преобразований для примитивных типов называются расширяющимися примитивными преобразованиями:

[..]

  • int для long, float или double

[..]

5.1.8. Конвертирование Unboxing

[..]

  • Из типа Integer для ввода int

Что должно произойти, это unboxing от Integer до int, а затем расширенное преобразование в long. Это фактически происходит в Oracle JDK (1.8.0.25).

Я считаю, что вы столкнулись с ошибкой компилятора в вашем JDK. Вероятно, вам следует попробовать обновленную версию или сообщить об ошибке с сопровождающими.