Подтвердить что ты не робот

Проблемы, связанные с параметрами типа в вызовах метода Java

Спецификация языка Java для Java 8 представляет собой пример вызова метода с аргументом типа в "Пример 4.11-1. Использование типа":

<S> void loop(S s) {
    this.<S>loop(s); // <S> is the the type argument for the method call.
}

В этом примере аргумент поставляемого типа имеет смысл, но, по-видимому, аргументы типа для вызовов метода также могут быть избыточными и совершенно бессмысленными, а дженерики даже не должны быть задействованы. Например:

void m() { }

void test() {
    m(); 
    this.m(); 
    this.<Integer>m(); // Compiles and runs OK!
    this.<String, Byte, StringBuilder, Thread[], Throwable>m(); // Compiles and runs OK!
    <Integer>m(); // Won't compile: "illegal start of expression"
}

У меня возникает несколько вопросов:

  • Может ли кто-нибудь предложить обоснованную причину для Java, позволяющую использовать эти избыточные параметры типа? Признавая, что они не навредят, мне все же кажется, что компилятор может и должен уловить.

  • Этот код компилируется только при вызове метода с аргументами типа с префиксом "this.". В противном случае вы получите ошибки "незаконного начала выражения". Это ошибка? Не следует использовать какой-либо однозначный метод, который работает с "этим". также работают без этого. "

(Катализатор для этих вопросов ответ Oracle в отчет об ошибке, который я создал для интересной проблемы Java, кто-то поднял здесь на SO.)

ОБНОВЛЕНИЕ 18 сентября 2015 г.

Это не проблема; ссылки на методы проверяются с использованием тех же правил, что и простые методы - обратите внимание, что для обычных методов вы всегда можете использовать избыточные аргументы типа:

void m() { }
this.<String>m(); //legal

Ссылки на метод (и конструктор) просто наследуют это поведение, согласно 15.13: "Если ссылочное выражение метода имеет форму ReferenceType:: [TypeArguments] Identifier, потенциально применимыми методами являются методы-члены типа для поиска, имеющие соответствующее имя (заданное идентификатором), доступность, arity (n или n- 1) и введите аргумент arty (полученный из [TypeArguments]), как указано в §15.12.2.1."

  1. Поскольку этот ответ подтверждает, что информация TAsk уже указана ниже (включая цитирование соответствующего раздела JLS), я принял этот ответ.
4b9b3361

Ответ 1

Ниже приведены способы вызова метода:

JLS 15.12 перечисляет следующие способы вызова метода,

  • MethodName ( [ArgumentList] ) (Примечание: это не имеет аргумента типа)
  • TypeName.[TypeArguments] Identifier ( [ArgumentList] )
  • ExpressionName.[TypeArguments] Identifier ( [ArgumentList] )
  • Primary.[TypeArguments] Identifier ( [ArgumentList] )
  • super.[TypeArguments] Identifier ( [ArgumentList] )
  • TypeName.super.[TypeArguments] Identifier ( [ArgumentList] )

Итак, именно там, в спецификации языка Java, метод с выражением или именем типа может иметь аргументы типа, но обратите внимание, что при первом вызове метода вы не можете указать аргумент типа как незаконный.

Обратите внимание, что только this не разрешает это, но вызов static и super вызовы методов также могут иметь аргументы типа, и они полностью законны.

static void m() { }

void test() {
   ClassName.<Integer>m();//Also compiles
}

Кроме этого у вас будет следующее предупреждение,

Неиспользуемые аргументы типа для не общего метода m() ...

Что означает следующий оператор JLS 15.12.2.1,

В этом разделе подразумевается, что не общий метод может быть potentiallyприменимый к вызову, который предоставляет аргументы явного типа. Действительно, это может оказаться применимым. В этом случае тип аргументы просто игнорируются.

Он говорит, что он может оказаться применимым (во время выполнения)

Кроме того,

Это правило связано с проблемами совместимости и принципами взаимозаменяемости. Поскольку интерфейсы или суперклассы могут генерироваться независимо от их подтипов, , мы можем переопределить общий метод с не общим. Тем не менее, переопределяющий (не общий) метод должен быть применим к вызовам общего метода, включая вызовы, которые явно передают аргументы типа. В противном случае подтип не подменялся бы для его обобщенного супертипа.