Java 转换顺序
假设我有以下设置
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()
? - 在
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
- Casting
a
to typeC
then attempting to callfoo()
on it? - Calling
foo()
ona
and casting the result to typeC
?
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
(C)a.foo()
相当于(C)(a.foo())
,即问题中的#2。要获得#1,您必须编写
((C)a).foo()
。Java 语言规范没有以漂亮、易于阅读的摘要形式指定运算符优先级。
Sedgewick 和 Wayne 撰写的《Java 编程简介》的附录 A 有运算符优先级综合表。
Java 编程语言 的附录 B 有一个运算符优先级表,但它是不像塞奇威克那样完整。
仔细检查 Java 语言规范中的语法可以确定相关转换和方法调用表达式的相对优先级:
相关产生式以粗体显示。我们可以看到强制转换表达式与产生式
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:
The relevant productions are bolded. We can see that a cast expression matches the production
Expression3 : (Expression|Type) Expression3
. The method call matches the productionExpression3 : Primary {Selector} {PostfixOp}
by means of the productionPrimary: Identifier {. Identifier }[IdentifierSuffix]
. Putting this together, we see that the method call expression will be treated as a unit (anExpression3
) to be acted upon by the cast.Hmmm, the precedence chart is easier to follow... ;)
方法调用的运算符优先级高于类型转换,因此
(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 calla.foo()
and cast the result to typeC
. In contrast,((C) a).foo()
first castsa
to typeC
and then calls itsfoo()
method.