2015-08-28 4 views
11

Спецификация языка Ява для Java, 8 приведен пример вызова метода с аргументом типа в «Примере 4.11-1 Использование такого типа.»:Вопросы, относящиеся к типу параметров в методе Java вызывает

<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" 
} 

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

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

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

(Катализатор этих вопросов Oracle's response на сообщение об ошибке, я создал интересную проблему Java кто-то подняли here на SO.)

UPDATE Сентябрь 18, 2015

  1. Я поднял bug JDK-8098556 по этой проблеме с Oracle. Вот их ответ:

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

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

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

  1. С этого момента nse подтверждает информацию TAsk уже предоставил ниже (включая ссылки на соответствующий раздел JLS), я принял этот ответ.
+1

Не знаю, почему это разрешено, но в Eclipse, вы получите предупреждение «аргументы Неиспользуемого типа для отсутствия универсального метода т() типа теста, оно не должно быть параметрироваться с аргументами », что означает * Дон» сделайте это *. --- 'это. m() 'is * syntactically * valid и имеет значение, если' m' набирается, но ' m()' - это простой недопустимый синтаксис. – Andreas

+1

см. Http://stackoverflow.com/questions/28014853/what-is-the-point-of-allowing-type-witnesses-on-all-method-calls – ZhongYu

+0

Второй вопрос должен быть из-за некоторых трудностей синтаксического анализа/грамматики. например, 'x < m()' – ZhongYu

ответ

5

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

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 call и super вызовы методов могут также иметь аргументы типа, и они полностью законны.

static void m() { } 

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

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

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

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

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

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

Кроме того,

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

+1

Ваша цитата из JLS15.12.2.1, безусловно, указывает на то, что параметры типа переносятся/игнорируются, хотя кажется, что это необходимо для того, чтобы быть релевантным в сценарии, где нет дженериков, а вызываемый метод не имеет параметров. Андреас отметил в комментарии выше, что Eclipse по крайней мере дает предупреждение компилятора. Я использовал Oracle JDK 8u60, который не дает никакого предупреждения. – skomisa

Смежные вопросы