Java 8 autoboxing + generics: различное поведение в зависимости от метода

Я нашел кусок кода, который после переключения с Java 7 на Java 8 перестал компилироваться. Он не поддерживает ни одного нового Java 8, такого как лямбда или потоки.

Я сузил проблемный код до следующей ситуации:

GenericData<Double> g = new GenericData<>(1d);
Double d = g == null ? 0 : g.getData(); // type error!!!

Вы можете догадаться, чтоGenericDataконструктор имеет один параметр этого универсального типа иgetData() Метод возвращает только этот общий тип. (Полный исходный код см. Ниже.)

Теперь меня беспокоит то, что в Java 7 этот код компилируется просто отлично, тогда как в Java 8 я получаю следующую ошибку:

CompileMe.java:20: error: incompatible types: bad type in conditional expression
Double d = g == null ? 0 : g.getData();
                       ^
int cannot be converted to Double

Похоже, что Java 7 смогла сделать переход из int -> double -> Double, но Java 8 не может сразу перейти из int -> Double.

В частности, я нахожу забавным то, что Java 8делает принять код при измененииgetData() вdataто есть получить доступ кGenericDataзначение через саму переменную вместо метода-получателя:

Double d2 = g == null ? 0 : g.data; // now why does this work...

Итак, у меня есть два вопроса:

Почему Java 8 не выводит типы, такие как Java 7, и не переводит мое int в double, а затем в autoboxing double в Double?Почему эта проблема возникает только с универсальным методом, но не с универсальной переменной?

Полный исходный код:

public class CompileMe {
    public void foo() {
        GenericData<Double> g = new GenericData(1d);
        Double d = g == null ? 0 : g.getData(); // type error!!!
        Double d2 = g == null ? 0 : g.data; // now why does this work...
    }
}

class GenericData<T> {
    public T data;
    public GenericData(T data) {
        this.data = data;
    }
    public T getData() {
        return data;
    }
}

Чтобы проверить это, запустите компилятор следующим образом:

javac -source 1.7 -target 1.7 CompileMe.java   # ok (just warnings)
javac -source 1.8 -target 1.8 CompileMe.java   # error (as described above)

Наконец, в случае, если это имеет значение: я запускаю Windows 8 и Java 1.8.0_112 (64-разрядная версия).

Ответы на вопрос(4)

Ваш ответ на вопрос