Я нашел фрагмент кода, который после переключения с 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
с помощью самой переменной вместо метода getter:
Double d2 = g == null ? 0 : g.data; // now why does this work...
Итак, у меня есть два вопроса:
- Почему Java 8 не выдает такие типы, как Java 7, и не меняет мой int, чтобы удвоить значение до автоматического использования 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-разрядный).