本文介绍了Java 转换顺序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有以下设置

class A {B foo();}C类扩展B{}//之后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() 的特定参考,尽管我不知道这会如何改变行为.

解决方案

(C)a.foo() 等价于 (C)(a.foo())代码>,即问题中的#2.

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

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

附录 AJava 编程简介,作者 SedgewickWayne 有一个综合的运算符优先级表.

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

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

表达:表达式1 [赋值运算符表达式1]]表达式1:Expression2 [Expression1Rest]表达式 1 休息:?表达式:表达式 1表达式2:Expression3 [Expression2Rest]表达 2 休息:{中缀表达式3}Expression3 实例类型表达式3:PrefixOp 表达式3(表达式 | 类型)表达式 3主要 {Selector} {PostfixOp}基本的:ParExpressionNonWildcardTypeArguments(ExplicitGenericInvocationSuffix | 此参数)这 [参数]超级后缀文字新造物主标识符 { .标识符 }[ IdentifierSuffix]基本类型 {[]} .classvoid.class

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

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

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.

解决方案

(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... ;)

这篇关于Java 转换顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 20:29