假设我有以下设置

class A {
    B foo();
}

class C extends B {

}

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

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

当我做(C)a.foo()
  • 强制转换a以键入C,然后尝试在其上调用foo()吗?
  • foo()上调用a并将结果转换为C类型?

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

    这是对ObjectInputStream.readObject()的特定引用,尽管我看不到它将如何改变行为。

    最佳答案

    (C)a.foo()(C)(a.foo())等效,即问题中的#2。

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

    Java语言规范没有在易于理解的摘要中指定运算符优先级。

    Sedgewick和Wayne撰写的Java编程简介中的Appendix A具有完整的运算符优先级表。

    The Java Programming Language的附录B有一个运算符优先级的表,但不如Sedgewick的完整。

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

    表达式:
    Expression1 [AssignmentOperator Expression1]

    表达式1:
    Expression2 [Expression1Rest]

    Expression1Rest:
    ?表达式:Expression1

    表达式2:
    Expression3 [Expression2Rest]

    Expression2Rest:
    {InfixOp Expression3}
    Expression3 instanceof类型

    表达式3:
    PrefixOp表达式3
    (表达式|类型)Expression3
    主要 {选择器} {PostfixOp}

    主:
    ParExpression
    NonWildcardTypeArguments(ExplicitGenericInvocationSuffix |此参数)
    这个[参数]
    super 后缀
    文字
    新造物主
    标识符{。标识符} [IdentifierSuffix]
    BasicType {[]} .class
    无效类

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

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

    10-06 04:58