Предположим, что у меня есть общий class Generic<A extends BaseType>.
Есть ли заметная разница в отношении спецификации языка Java между двумя объявлениями типа?
Generic<?>
Generic<? extends BaseType>
Как насчет вложенных подстановочных знаков?
List<Generic<?>>
List<Generic<? extends BaseType>>
Размышляя об этом, я бы предположил, что это эквивалентно. Generic указывает, что параметр типа A имеет BaseType для верхней границы.
Таким образом, подстановочный знак всегда должен быть "автоматически" или "неявно" ограничен BaseType, независимо от того, я конкретно его укажу или нет.
Ниже я пытаюсь примирить свою интуицию с JLS.
Мне не удалось найти информацию о "неявных" границах, поэтому я начал с рассмотрения правил подтипирования.
Считывая раздел JLS о подтипирование $4.10.2, он говорит:
Учитывая объявление универсального типа
C<F1,...,Fn>(n > 0), прямые супертипы параметризованного типаC<T1,...,Tn>, , где Ti (1 ≤ я ≤ n) являются типом, все из следующего:
D<U1 θ,...,Uk θ>, гдеD<U1,...,Uk>- общий тип, являющийся прямым супертипом типового типаC<T1,...,Tn>, а θ - подстановка [F1: = T1,..., Fn: = Tn].
C<S1,...,Sn>, где Si содержит Ti (1 ≤ я ≤ n) (п. 4.5.1).
(акцент мой)
Из того, что я понимаю, "подстановочные знаки" не считаются "типами" в JLS. Таким образом, это не может применяться к первым двум, но оно применимо к двум примерам List.
Вместо этого это должно применяться:
Учитывая объявление универсального типа
C<F1,...,Fn>(n > 0), прямые супертипы параметризованного типаC<R1,...,Rn>, где хотя бы один из Ri (1 ≤ я ≤ n) является аргументом типа подстановочного символа, являются прямыми супертипами параметризованного типаC<X1,...,Xn>, который является результатом применения преобразования захвата вC<R1,...,Rn>(§5.1.10).
(акцент мой)
Применение конверсия захвата $5.1.10 в Generic<?> и Generic<? extends BaseType>; Я думаю, что я получаю те же границы по новым переменным типа. После преобразования захвата я могу использовать правила "содержит", чтобы установить подтипирование.
В первом примере через
Если Ti является аргументом типа подстановочного типа (п. 4.5.1) формы?, то Si - переменная нового типа, верхняя граница которой Ui [A1: = S1,..., An: = Sn] и чьи нижняя граница - нулевой тип (§4.1).
Так как A 1 is BaseType, свежая переменная имеет верхнюю границу BaseType.
Во втором случае через
Если Ti является аргументом типа подстановочной формы формы? расширяет Bi, то Si является переменной нового типа, верхняя граница которой равна glb (Bi, Ui [A1: = S1,..., An: = Sn]), нижняя граница которой является нулевым типом.
glb (V1,..., Vm) определяется как V1 и... и Vm.
Я получаю glb(BaseType, BaseType), что опять же BaseType.
Итак, похоже, что отношение подтипирования между Generic<?> и Generic<? extends BaseType> идет в обоих направлениях в соответствии с JLS, которое соответствует моей интуиции.
Для вложенных подстановочных знаков я бы использовал правило "содержит" :
Утверждается, что аргумент типа T1 содержит другой аргумент типа T2, записанный T2 <= T1, если набор типов, обозначаемый T2, является предположительно a подмножество множества типов, обозначаемое T1 под рефлексивным и переходное замыкание следующих правил (где <: обозначает подтипирование (§4.10)):
? extends T <= ? extends S if T <: S
? extends T <= ?
? super T <= ? super S if S <: T
? super T <= ?
? super T <= ? extends Object
T <= T
T <= ? extends T
T <= ? super T
В сочетании с
C<S1,...,Sn>, where Si contains Ti (1 ≤ i ≤ n) (§4.5.1).
сверху, я получаю:
List<Generic<?>> является прямым супертипом List<Generic<? extends BaseType>>, если Generic<?> содержит Generic<? extends BaseType>>
Хотя, я не вижу, как я использую правило contains. Единственной дополнительной информацией, которую я могу использовать, является подтипирование в соответствии с правилами. Я уже знаю, что подтипирование происходит в обоих направлениях между двумя типами.
Хотя, если содержит ответ с подтипированием между ними, я мог бы также показать, что List<String> является подтипом List<Object>, которого он не является и не должен быть.
Далее, мне нужно показать что-то из формы Type <= OtherType, и единственным правилом с правой частью формы "type" является T <= T, поэтому эти правила, похоже, вообще не помогают.
Как мне получить, что List<Generic<?>> и List<Generic<? extends BaseType>> являются подтипами друг друга через JLS?