Java铸造订单

cor*_*iKa 11 java casting default

假设我有以下设置

class A {
    B foo();
}

class C extends B {

}

// later
A a = new A();
C theFoo = (C)a.foo();
Run Code Online (Sandbox Code Playgroud)

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

当我这样做的时候(C)a.foo(),是吗?

  1. 转换a为类型C然后尝试调用foo()它?
  2. 调用foo()a铸造的结果类型C

我发现很难确定,并且总是只是在谨慎的情况下使用额外的括号(这对于可读性来说并不是一个坏主意,但现在我很好奇)

这是具体的参考,ObjectInputStream.readObject()虽然我没有看到这将如何改变行为.

WRe*_*ach 14

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

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

Java语言规范没有在一个简单易读的摘要中指定运算符优先级.

附录A在Java编程简介由塞奇威克和韦恩运算符优先级的综合表.

Java编程语言的附录B 有一个运算符优先级表,但它不像Sedgewick那样完整.

仔细检查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.方法调用通过生产匹配Expression3 : Primary {Selector} {PostfixOp}生产Primary: Identifier {. Identifier }[IdentifierSuffix].将它们放在一起,我们看到方法调用表达式将被视为一个单元(a Expression3),以便由强制转换器执行操作.

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


Jos*_*sen 5

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