Каковы формальные условия, при которых параметр подстановки в универсальном типе Java находится в его пределах?

С параметризованными типами в Java, как правила, проверяющие, находится ли параметр в пределах его привязки, работают точно для подстановочных знаков ?

Дан такой класс:

class Foo {}

Экспериментируя с тем, что принимает компилятор, узнает, что:

  • A ? extends подстановочный знак разрешен с использованием несвязанного типа интерфейса: Foo extends Runnable> действительно
  • A ? extends подстановочный знак с использованием несвязанного типа класса не допускается: Foo extends Thread> недопустим. В этом есть смысл, потому что ни один тип не может быть подтипом одновременно Number и Thread
  • In a ? super подстановочный знак, нижняя граница подстановочного знака должна быть подтипом границы переменной типа: Foo super Runnable> не допускается, потому что Runnable не является подтипом Number . Опять же, это ограничение имеет смысл.

Но где эти правила определены? Глядя на раздел 4.5 спецификации языка Java, я не вижу ничего, что отличает интерфейсы от классов; и при применении моей интерпретации JLS Foo super Runnable> считается допустимым. Так что я, наверное, что-то неправильно понял. Вот моя попытка:

Из этого раздела JLS:

Параметризованный тип состоит из имени класса или интерфейса C и фактического списка аргументов типа . Ошибка времени компиляции, если C не является именем универсального класса или интерфейса или если количество аргументов типа в фактическом списке аргументов типа отличается от количества объявленных параметров типа C. В дальнейшем, когда мы говорим типа класса или интерфейса, мы также включаем универсальную версию, если она явно не исключена. В этом разделе пусть A1, ..., An будут параметрами формального типа C, и пусть be Bi будет объявленной границей Ai. Обозначение [Ai: = Ti] обозначает замену переменной типа Ai на тип Ti для 1

Пусть P = G быть параметризованным типом. Это должно быть так, что после того, как P подвергается преобразованию захвата (§5.1.10), приводящему к типу G , для каждого фактического аргумента типа Xi, 1

Примените это к P = Foo super Runnable> : что дает C = Foo , n = 1, T1 = ?super Runnable и B1 = Число .

Для преобразования захвата применяется эта часть определения преобразования захвата :

Если Ti является аргументом типа подстановочного знака для форма? super Bi, тогда Si - переменная нового типа, верхняя граница которой равна Ui [A1: = S1, ..., An: = Sn], а нижняя граница - Bi.

Это дает G = Foo где X - это переменная нового типа с верхней границей Number и нижней границей Runnable . Я не вижу ничего явно запрещающего такую ​​переменную типа.

В B1 = Number нет переменных типа, поэтому Bi [A1: = X1, ..., An: = Xn] равно по-прежнему просто Число . X имеет число как верхнюю границу (исходя из преобразования захвата) и согласно правилам подтипов «Прямые супертипы переменной типа - это перечисленные типы in its bound », поэтому X <:> Number (= Bi [A1: = X1, ..., An: = Xn]), поэтому этот параметр находится в пределах его границ. (Но это не так!)

Следуя тем же рассуждениям , каждый подстановочный знак находится в пределах своих границ, поэтому здесь что-то не так ... Но где именно это рассуждение пошло не так? Как эти правила работают при правильном применении?

11
задан Wouter Coekaerts 9 August 2011 в 21:07
поделиться