Почему общий листинг списка <? extends Set..> to List <Set..> преуспеть на Sun JDK 6, но не скомпилировать на Oracle JDK 7?
Следующий код
class GenericCompilationFailureDemo {
List<? extends GenericCompilationFailureDemo> newList() {
return new ArrayList<GenericCompilationFailureDemo>();
};
void useList() {
List<GenericCompilationFailureDemo> list =
(List<GenericCompilationFailureDemo>) newList();
}
List<? extends Set<GenericCompilationFailureDemo>> newListOfSpecificSets() {
return new ArrayList<Set<GenericCompilationFailureDemo>>();
};
void useListOfSpecificSets() {
List<Set<GenericCompilationFailureDemo>> listOfSpecificSets =
(List<Set<GenericCompilationFailureDemo>>) newListOfSpecificSets();
}
List<? extends Set<? extends GenericCompilationFailureDemo>> newListOfSets() {
return new ArrayList<Set<? extends GenericCompilationFailureDemo>>();
};
void useListOfSet() {
List<Set<? extends GenericCompilationFailureDemo>> listOfSets =
(List<Set<? extends GenericCompilationFailureDemo>>) newListOfSets();
}
}
компилируется под Sun JDK 1.6.0_20 (64-разрядная версия в Windows Vista, но я не думаю, что это имеет значение), но приводит к следующему сбою компиляции в Oracle JDK 1.7.0_01 (той же платформе):
[ERROR] src\main\java\GenericCompilationFailureDemo.java:[56,78] error: inconvertible types
Обратите внимание, что первые два типа "extends-to-specific-type" в useList
и useListOfSpecificSets
оба по-прежнему преуспевают в 1.7.0_01, поэтому, похоже, это что-то связано с "двойным родовым расширением".
Любые идеи, которые могли бы измениться между 6 и 7, и было ли наблюдаемое поведение в соответствии со спецификацией или ошибкой?
отредактирован в ответ на комментарий Sanjay:
@Sanjay: Ага, интересно! Здесь вывод java -version
:
java version "1.7.0_01"
Java(TM) SE Runtime Environment (build 1.7.0_01-b08)
Java HotSpot(TM) 64-Bit Server VM (build 21.1-b02, mixed mode)
И вот результат javac GenericCompilationFailureDemo.java
(тот же код, что и выше, с операторами импорта для List, ArrayList и Set):
GenericCompilationFailureDemo.java:30: error: inconvertible types
(List<Set<? extends GenericCompilationFailureDemo>>) newListOfSets()
;
^
required: List<Set<? extends GenericCompilationFailureDemo>>
found: List<CAP#1>
where CAP#1 is a fresh type-variable:
CAP#1 extends Set<? extends GenericCompilationFailureDemo> from capture of ?
extends Set<? extends GenericCompilationFailureDemo>
Note: GenericCompilationFailureDemo.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
1 error
Ответы
Ответ 1
Это, по-видимому, ошибка javac7. Он должен быть разрешен для каждого правила преобразования кастома [1]
Одно из правил позволяет сузить ссылочное преобразование... с последующим непроверенным преобразованием
Задание List<A> => List<B>
разрешено этим правилом
List<A> => List // narrowing reference conversion
List => List<B> // unchecked conversion
Это не вся история; спецификация имеет дополнительные правила, запрещающие кастинг как List<String>=>List<Integer>
, поскольку они являются явно различимыми параметризуемыми
типы. В то же время нет объектов, принадлежащих к двум типам, поэтому компилятор считает, что лучше отказаться от этой очевидной ошибки программирования. (Вы можете обойти его явно List<String>=>List=>List<Integer>
)
Последнее правило здесь не применяется; поэтому он выглядит как ошибка javac7.
Почему последнее правило не применяется: поэтому мы отбрасываем List<? extends A>
в List<A>
. Здесь преобразование захвата применяется к List<? extends A>
[2], поэтому мы фактически отбрасываем List<T>
в List<A>
, где T
- это новая переменная типа с верхней границей A
.
Вопрос заключается в том, являются ли List<T>
и List<A>
доказуемо различными параметризованными типами. Я понимаю, что он ложный (он должен быть ложным для ваших первых двух примеров для компиляции). Так как T
является переменной типа, он может принять значение, чтобы сделать List<T>
и List<A>
тем же параметризованным типом (т.е. Когда T=A
). Это рассуждение должно работать для любого типа A
.
[1] http://java.sun.com/docs/books/jls/third_edition/html/conversions.html#5.5
[2] http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#341306