Я нашел фрагмент кода, который после переключения с Java 7 на Java 8 прекратил компиляцию. В нем нет ни одного нового материала Java 8, такого как лямбда или потоки.Java 8 autoboxing + generics: различное поведение с переменной по сравнению с методом
я сузил проблемный код вниз к следующей ситуации:
GenericData<Double> g = new GenericData<>(1d);
Double d = g == null ? 0 : g.getData(); // type error!!!
Вы можете, вероятно, предположить, что конструктор GenericData
«s имеет один параметр этого общего типа и метод 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-не выводить типы, такие как Java 7 и бросить мой Int удвоить, прежде чем Autoboxing двойного 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 -немного).
Только для записи: вы используете сырой тип там; на строке 'g = new GenericData'. Наверное, не первопричина, но точно не помогает. И кстати: я просто перепробовал проблему с IBM JDK 1.8 ... действительно интересно. – GhostCat
@Quota действительно интересен, кстати компилируется отлично с последним jdk-9 – Eugene
Попробуйте взглянуть на этот вопрос SO: [Java 8 и обобщенный вывод типа цели] (http://stackoverflow.com/questions/19934204/ java-8-and-generalized-target-type-inference) –