Вызов метода для нового объекта в Java без круглых скобок: порядок нарушения операций?

Согласно эта таблица приоритетов и ассоциативности Java-операторов, доступ к члену имеет более высокий приоритет, чем оператор new.

Однако, учитывая класс myClass и нестационарную функцию-член myFunction, следующая строка кода действительна:

new myClass().myFunction();

Если . оценивается до new, как эта строка может быть выполнена? Другими словами, почему не нужны скобки?

(new myClass()).myFunction();

Я предполагаю, что, поскольку () имеет приоритет с ., сначала оценивается myClass(), поэтому компилятор знает даже до того, как оценил ключевое слово new, что конструктор myClass с нулевыми параметрами называется. Однако это все еще кажется, что первая строка должна быть идентична new (myClass().myFunction());, что не так.

Ответ 1

Это связано с тем, как определяется грамматика языка Java. Приоритет операторов вступает в игру только тогда, когда одна и та же лексическая последовательность может анализироваться двумя разными способами, но это не так.

Почему?

Поскольку распределение определено в:

Primary: 
  ...
  new Creator

тогда как вызов метода определяется в:

Selector:
  . Identifier [Arguments]
  ...

и оба используются здесь:

Expression3: 
  ...
  Primary { Selector } { PostfixOp }

так что происходит, что

new myClass().myFunction();

анализируется как

         Expression
             |
             |
    ---------+--------
    |                |
    |                |
  Primary        Selector
    |                |
    |                |
 ---+---            ...
 |     |
new   Creator 

Таким образом, выбор невозможен по приоритету, потому что Primary сокращен раньше. Имейте в виду, что для особой ситуации вроде

new OuterClass.InnerClass()

имя класса фактически анализируется перед оператором new, и есть правила, чтобы справиться с этим делом. Проверьте грамматику, если вы хотите их увидеть.

Ответ 2

Я не согласен с выводами, сделанными на диаграмме Джека. Когда грамматика написана, ее нетерминалы и структура предназначены для реализации приоритета и ассоциативности описываемого языка. Вот почему классический BNF для выражений вводит "нетерминалы термина" и "фактор", чтобы обеспечить нормальное умножение до добавления приоритета арифметики.

Таким образом, тот факт, что "Первичный → Новый Создатель" и "Выражение → Первичный Селектор" в грамматике означает, что "новый Создатель" находится на более высоком уровне приоритета, чем "Первичный Селектор".

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