Рассмотрим следующий пример кода:
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List list = new ArrayList<Integer>();
String response = getProducer(list).get();
}
static Producer<String> getProducer(List<Integer> list) {
return new Producer<String>();
}
}
class Producer<T> {
T get() {
return null;
}
}
При компиляции в Java 7 он просто выводит ожидаемое предупреждение для getProducer(list)
:
Предупреждение: (7, 39) java: unchecked conversion требуется:
java.util.List<java.lang.Integer>
найдено:java.util.List
Однако при компиляции в Java 8 он вызывает следующую ошибку для назначения response = getProducer(list).get()
:
Ошибка: (7, 48) java: несовместимые типы:
java.lang.Object
не может быть преобразован вjava.lang.String
Похоже, что тип, возвращаемый из getProducer(list)
, не является Producer<String>
, но стирается Producer
(что также подтверждается с помощью функции "extract variable" в среде IDE). Это очень озадачивает, потому что метод getProducer
всегда возвращает Producer<String>
.
Как ни странно, это можно было бы устранить, избегая непроверенного преобразования при вызове метода getProducer
, либо:
- Измените тип параметра
getProducer
сList<Integer>
наList
- Измените тип переменной
List
сList
наList<Integer>
Обновление
- Java используется Oracle JDK 1.8.0_40
- Я также попытался использовать исходные и целевые параметры с 1.5 по 1.7 с компилятором Java 8, и результат был таким же.
Вопросы
- Как общий тип переданного аргумента влияет на общий тип метода возвращаемое значение, в то время как общий тип возвращаемого значения фиксируется в сигнатуре метода?
- Почему существует такое отстало-несовместимое изменение в поведении между Java 7 и Java 8?