在Java中调用新对象的方法而不带括号:操作顺序违规?

2022-09-01 04:36:49

根据此 Java 运算符优先级和关联性表,成员访问的优先级高于运算符。new

但是,给定一个类和一个非静态成员函数,以下代码行是有效的:myClassmyFunction

new myClass().myFunction();

如果之前计算过,这行怎么能执行呢?换句话说,为什么不需要括号?.new

(new myClass()).myFunction();

我的猜测是,由于与 共享优先级,因此首先计算 ,因此编译器甚至在计算关键字之前就知道正在调用具有零参数的构造函数。但是,这似乎仍然意味着第一行应该与 相同,但事实并非如此。().myClass()newmyClassnew (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 运算符优先级和关联性表不正确的证据。


推荐