Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

  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.

like image 984
corsiKa Avatar asked Apr 23 '11 04:04

corsiKa


People also ask

How many types of casting are there in Java?

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.

What is casting in Java with example?

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

When type casting is used in Java?

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.

What is type casting with example?

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.


1 Answers

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

like image 63
WReach Avatar answered Oct 11 '22 17:10

WReach