关于解析:Java 编译器如何解析类型转换?

How does a Java compiler parse typecasts?

一个简单的表达式,如

1
(x) - y

的解释取决于 x 是否是类型名称。如果 x 不是类型名称,(x) - y 只是从 x 中减去 y。但是如果 x 是一个类型名称,(x) - y 计算 y 的负数并将结果值转换为类型 x.

在典型的 C 或 C 编译器中,x 是否是类型的问题是可以回答的,因为解析器在处理 typedef 或 struct 声明后立即将此类信息传达给词法分析器。 (我认为这种违反级别的要求是 C 设计中最讨厌的部分。)

但在 Java 中,x 可能要在源代码的后面才定义。 Java 编译器如何消除这种表达式的歧义?

很明显,Java 编译器需要多次通过,因为 Java 不需要使用前声明。但这似乎意味着第一遍必须在解析表达式上做一个非常草率的工作,然后在以后的遍中做另一个更准确的表达式解析。那看起来很浪费。

有没有更好的方法?


我想我已经找到了让我满意的解决方案。感谢 mmyers,我意识到我需要检查类型转换语法的正式规范。

歧义是由 +- 既是一元运算符又是二元运算符引起的。 Java通过这个语法解决了这个问题:

1
2
3
CastExpression:
        ( PrimitiveType Dimsopt ) UnaryExpression
        ( ReferenceType ) UnaryExpressionNotPlusMinus

(参见 http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#238146)

因此,'+''-' 在转换的 ')' 之后立即被明确禁止,除非转换使用原始类型——编译器事先知道这些类型。


我刚刚测试过了,这个代码:

1
2
Double y = new Double(0.1);
System.out.println((Double)-y);

给出编译错误:

operator - cannot be applied to Double, java.lang.Double.

在 -y 周围加上括号使其编译正常。显然,Java 通过在语法中不允许它来解决这个问题(如果这是正确的术语;我不是编译器方面的专家)。