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
a
to type C
then attempting to call foo()
on it?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.
There are two types of casting in Java as follows: Widening Casting (automatically) – This involves the conversion of a smaller data type to the larger type size. Narrowing Casting (manually) – This involves converting a larger data type to a smaller size type.
Example: Converting double into an int int data = (int)num; Here, the int keyword inside the parenthesis indicates that that the num variable is converted into the int type. In the case of Narrowing Type Casting, the higher data types (having larger size) are converted into lower data types (having smaller size).
In Java, type casting is a method or process that converts a data type into another data type in both ways manually and automatically. The automatic conversion is done by the compiler and manual conversion performed by the programmer.
In type casting, the compiler automatically changes one data type to another one depending on what we want the program to do. For instance, in case we assign a float variable (floating point) with an integer (int) value, the compiler will ultimately convert this int value into the float value.
(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... ;)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With