问题 Java编译器如何解析类型转换?


一个简单的表达式

(x) - y

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

在典型的C或C ++编译器中,是否存在的问题 x 是一个类型或不是一个类型是可以回答的,因为解析器一旦处理了typedef或struct声明就将这些信息传递给词法分析器。 (我认为这种必要的违反水平是C设计中最糟糕的部分。)

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

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

有没有更好的办法?


8554
2017-12-30 17:19


起源



答案:


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

模棱两可是由于 + 和 - 既是一元运算符又是二元运算符。 Java通过这种语法解决了这个问题:

CastExpression:
        ( PrimitiveType Dimsopt ) UnaryExpression
        ( ReferenceType ) UnaryExpressionNotPlusMinus

(看到 http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#238146

所以, '+' 和 '-' 明确禁止之后立即禁止 ')' 除非演员使用原始类型 - 编译器先验地知道它。


8
2017-12-30 18:22



我懒得去查看规格(我不知道在哪里看)。 +1 - Michael Myers♦
考虑接受这个答案。 - Jeffrey Bosboom


答案:


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

模棱两可是由于 + 和 - 既是一元运算符又是二元运算符。 Java通过这种语法解决了这个问题:

CastExpression:
        ( PrimitiveType Dimsopt ) UnaryExpression
        ( ReferenceType ) UnaryExpressionNotPlusMinus

(看到 http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#238146

所以, '+' 和 '-' 明确禁止之后立即禁止 ')' 除非演员使用原始类型 - 编译器先验地知道它。


8
2017-12-30 18:22



我懒得去查看规格(我不知道在哪里看)。 +1 - Michael Myers♦
考虑接受这个答案。 - Jeffrey Bosboom


我只是测试了它,这段代码:

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

给出编译错误:

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

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


2
2017-12-30 17:32



我没有downvote,但是如果不是Double,你使用了双倍编译器会允许它,因为 运营商 -  可以应用于双打。我认为这是因为这种不确定性而被低估了。 - David Rodríguez - dribeas
从Java 1.5开始,你可以使用任何带双打,浮点数等算术运算符(因为自动装箱)。正如我所说,添加括号使它编译没有错误。 - Michael Myers♦
+1因为我认为没有任何理由这个答案应该被投票给否定 - dancavallaro