Java casting order
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.
Solution 1:
(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... ;)
Solution 2:
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.