在没有括号的Java中调用新对象的方法:操作违规的顺序?
根据此Java运算符优先级和关联性表 ,成员访问优先级高于new
运算符。
但是,给定一个类myClass
和一个非静态成员函数myFunction
,以下代码行是有效的:
new myClass().myFunction();
如果.
在new
之前评估,这条线怎么能被执行? 换句话说,为什么不需要括号?
(new myClass()).myFunction();
我的猜测是因为()
分享优先权.
,首先评估myClass()
,因此编译器甚至在评估new
关键字之前就知道调用了带有零参数的myClass
构造函数。 但是,这似乎仍然暗示第一行应该与new (myClass().myFunction());
,情况并非如此。
这是因为定义了Java语言的语法 。 运算符的优先级恰好在相同的词汇序列可以用两种不同的方式解析时发挥作用,但事实并非如此。
为什么?
因为分配定义如下:
Primary: ... new Creator
方法调用定义如下:
Selector: . Identifier [Arguments] ...
这两个都用在这里:
Expression3: ... Primary { Selector } { PostfixOp }
那会发生什么呢
new myClass().myFunction();
被解析为
Expression | | ---------+-------- | | | | Primary Selector | | | | ---+--- ... | | new Creator
因此,根据优先级没有选择,因为Primary
节点之前已减少。 请注意,对于特殊情况喜欢
new OuterClass.InnerClass()
类名实际上是在new
运算符之前解析的,并且确实有处理该情况的规则。 如果你想看到它们,请检查语法。
我不同意杰克图中得出的结论。 在编写语法时,其非终结符和结构旨在实现所描述语言的优先级和关联性。 这就是为什么表达式的经典BNF引入了“术语”和“因子”非终结符 – 在算术的加法优先级之前强制执行正常乘法。
因此,语法中的“Primary – > new Creator”和“Expression – > Primary Selector”意味着“new Creator”的优先级高于“Primary Selector”。
在我看来,语法是Java运算符优先级和关联表不正确的证据。