37

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

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

new myClass().myFunction();

如果.是之前评估过new的,这行怎么执行?换句话说,为什么不需要括号?

(new myClass()).myFunction();

我的猜测是,由于()与 共享优先级.,因此myClass()首先评估 ,因此编译器甚至在评估new关键字之前就知道myClass正在调用具有零参数的构造函数。但是,这似乎仍然暗示第一行应该与 相同new (myClass().myFunction());,但事实并非如此。

4

2 回答 2

44

这是因为Java语言的语法是如何定义的。仅当可以以两种不同的方式解析相同的词汇序列时,运算符的优先级才起作用,但事实并非如此。

为什么?

因为分配定义在:

Primary: 
  ...
  new Creator

而方法调用定义在:

Selector:
  . Identifier [Arguments]
  ...

两者都在这里使用:

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

所以发生的事情是

new myClass().myFunction();

被解析为

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

所以没有根据优先级选择,因为Primary之前减少了。请注意,对于特殊情况,例如

new OuterClass.InnerClass()

类名实际上是在new运算符之前解析的,并且确实有处理这种情况的规则。如果您想查看它们,请检查语法。

于 2013-05-13T00:07:24.030 回答
3

我不同意从杰克的图表中得出的结论。编写语法时,其非终结符和结构旨在实现所描述语言的优先级和关联性。这就是为什么表达式的经典 BNF 引入了“术语”和“因子”非终结符 - 以在算术加法优先级之前强制执行正常乘法。

所以语法中的“Primary -> new Creator”和“Expression -> Primary Selector”这一事实意味着“new Creator”的优先级高于“Primary Selector”。

在我看来,语法是 Java 运算符优先级和关联性表不正确的证据。

于 2017-03-16T19:43:20.313 回答