Java 转换顺序

发布于 2024-11-03 03:21:45 字数 517 浏览 3 评论 0原文

假设我有以下设置

class A {
    B foo();
}

class C extends B {

}

// later
A a = new A();
C theFoo = (C)a.foo();

我们知道 a.foo() 返回类型 B。

当我执行 (C)a.foo() 时,是否会

  1. 强制转换 a 输入 C 然后尝试调用 foo()
  2. a 上调用 foo() 并将结果转换为类型 C

我发现很难确定,并且总是谨慎地使用额外的括号(这不是一个坏主意,为了可读性,但现在我很好奇)

这是具体参考 ObjectInputStream.readObject() 虽然我不知道这会如何改变行为。

Let's say I have the following setup

class A {
    B foo();
}

class C extends B {

}

// later
A a = new A();
C theFoo = (C)a.foo();

We know a.foo() returns type B.

When I do (C)a.foo(), is it

  1. Casting a to type C then attempting to call foo() on it?
  2. Calling foo() on a and casting the result to type C?

I'm finding it difficult to determine, and have always just played on the side of caution with extra parenthesis (which isn't a bad idea, for readability, but now I'm curious)

This is in specific reference to ObjectInputStream.readObject() although I don't see how that would change the behavior.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

鼻尖触碰 2024-11-10 03:21:45

(C)a.foo() 相当于 (C)(a.foo()),即问题中的#2。

要获得#1,您必须编写((C)a).foo()

Java 语言规范没有以漂亮、易于阅读的摘要形式指定运算符优先级。

Sedgewick 和 Wayne 撰写的《Java 编程简介》的附录 A 有运算符优先级综合表。

Java 编程语言 的附录 B 有一个运算符优先级表,但它是不像塞奇威克那样完整。

仔细检查 Java 语言规范中的语法可以确定相关转换和方法调用表达式的相对优先级:

Expression:
        Expression1 [AssignmentOperator Expression1]]

Expression1:
        Expression2 [Expression1Rest]

Expression1Rest:
        ?   Expression   :   Expression1

Expression2 :
        Expression3 [Expression2Rest]

Expression2Rest:
        {InfixOp Expression3}
        Expression3 instanceof Type

Expression3:
        PrefixOp Expression3
        (   Expression | Type   )   Expression3
        Primary {Selector} {PostfixOp}

Primary:
        ParExpression
        NonWildcardTypeArguments (ExplicitGenericInvocationSuffix | this Arguments)
        this [Arguments]
        super SuperSuffix
        Literal
        new Creator
        Identifier { . Identifier }[ IdentifierSuffix]
        BasicType {[]} .class
        void.class

相关产生式以粗体显示。我们可以看到强制转换表达式与产生式 Expression3 : (Expression|Type) Expression3 相匹配。该方法调用通过产生式 Primary: Identifier { 来匹配产生式 Expression3 : Primary {Selector} {PostfixOp}。标识符}[IdentifierSuffix]。将它们放在一起,我们看到方法调用表达式将被视为一个由强制转换执行的单元(Expression3)。

嗯,优先级图表更容易遵循......;)

(C)a.foo() is equivalent to (C)(a.foo()), i.e. #2 in the question.

To get #1, you would have to write ((C)a).foo().

The Java language specification does not specify operator precedence in a nice, easy-to-read summary.

Appendix A of Introduction to Programming in Java by Sedgewick and Wayne has a comprehensive table of operator precedence.

Appendix B of The Java Programming Language has a table of operator precedence, but it is not as complete as Sedgewick's.

A close inspection of the grammar in the Java Language Specification can determine the relative precedences of the cast and method call expressions in question:

Expression:
        Expression1 [AssignmentOperator Expression1]]

Expression1:
        Expression2 [Expression1Rest]

Expression1Rest:
        ?   Expression   :   Expression1

Expression2 :
        Expression3 [Expression2Rest]

Expression2Rest:
        {InfixOp Expression3}
        Expression3 instanceof Type

Expression3:
        PrefixOp Expression3
        (   Expression | Type   )   Expression3
        Primary {Selector} {PostfixOp}

Primary:
        ParExpression
        NonWildcardTypeArguments (ExplicitGenericInvocationSuffix | this Arguments)
        this [Arguments]
        super SuperSuffix
        Literal
        new Creator
        Identifier { . Identifier }[ IdentifierSuffix]
        BasicType {[]} .class
        void.class

The relevant productions are bolded. We can see that a cast expression matches the production Expression3 : (Expression|Type) Expression3. The method call matches the production Expression3 : Primary {Selector} {PostfixOp} by means of the production Primary: Identifier {. Identifier }[IdentifierSuffix]. Putting this together, we see that the method call expression will be treated as a unit (an Expression3) to be acted upon by the cast.

Hmmm, the precedence chart is easier to follow... ;)

信愁 2024-11-10 03:21:45

方法调用的运算符优先级高于类型转换,因此 (C) a.foo() 将首先调用 a.foo() 并将结果转换为类型 C。相反,((C) a).foo() 首先将 a 转换为类型 C,然后调用其 foo()方法。

Method call has a higher operator precedence than type casting, so (C) a.foo() will first call a.foo() and cast the result to type C. In contrast, ((C) a).foo() first casts a to type C and then calls its foo() method.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文