What Is the Priority of Casting in Java

What is the priority of casting in java?

See this table on operator precedence to make things clearer. Simply put, a cast takes precedence over a division operation, so it would give the same output as

int s = ((double)t) / 2;

As knoight pointed out, this is not technically the same operation as it would be without the parentheses, since they have a priority as well. However, for the purposes of this example, it will offer the same result, and is for all intents and purposes equivalent.

Precedence in expression including parentheses and int cast in java

You almost got it. The only difference (which doesn't matter for the result) is that the cast is evaluated
before the subtraction, and you're using integer division:

  1. 4 * 4 + 5 = 16 + 5 = 21
  2. Math.sqrt(21) ~ 4.58
  3. (int) 4.58 = 4 (cast first)
  4. 4 - 1 = 3
  5. 3 / 2 = 1 (integer division)

Java casting order

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

Type Casting, Operator Precedence or something else?

This is just a sequence of casts and number/char conversions:

int i = (byte) +(char) -(int) +(long) -1;

can be made verbose as:

int a = -1;
long b = (long) a;
int c = (int) -b; //makes it positive
char d = (char) c;
byte e = (byte) d;
int f = e;

System.out.println(f);

Java Precedence - Casting and Bitwise Operators

This is due to how operator precedence and associativity works in Java.1

Unfortunately, the Oracle Java Tutorial provides only a partial overview, and the Java Language Specification is not of great help either, as it mostly leaves the exercise of figuring out operator precedence to the reader by stating:

Precedence among operators is managed by a hierarchy of grammar productions.

In general, expressions are evaluated from left to right. In terms of operator precedence, the following table2 applies:

╔═══════╦══════════════╦══════════════════════╦═════════════════╗
║ Level ║ Operator ║ Description ║ Associativity ║
╠═══════╬══════════════╬══════════════════════╬═════════════════╣
║ 16 ║ [] ║ access array element ║ left to right ║
║ ║ . ║ access object member ║ ║
║ ║ () ║ parentheses ║ ║
╠═══════╬══════════════╬══════════════════════╬═════════════════╣
║ 15 ║ ++ ║ unary post-increment ║ not associative ║
║ ║ -- ║ unary post-decrement ║ ║
╠═══════╬══════════════╬══════════════════════╬═════════════════╣
║ 14 ║ ++ ║ unary pre-increment ║ right to left ║
║ ║ -- ║ unary pre-decrement ║ ║
║ ║ + ║ unary plus ║ ║
║ ║ - ║ unary minus ║ ║
║ ║ ! ║ unary logical NOT ║ ║
║ ║ ~ ║ unary bitwise NOT ║ ║
╠═══════╬══════════════╬══════════════════════╬═════════════════╣
║ 13 ║ () ║ cast ║ right to left ║
║ ║ new ║ object creation ║ ║
╠═══════╬══════════════╬══════════════════════╬═════════════════╣
║ 12 ║ * ║ multiplicative ║ left to right ║
║ ║ / ║ ║ ║
║ ║ % ║ ║ ║
╠═══════╬══════════════╬══════════════════════╬═════════════════╣
║ 11 ║ + - ║ additive ║ left to right ║
║ ║ + ║ string concatenation ║ ║
╠═══════╬══════════════╬══════════════════════╬═════════════════╣
║ 10 ║ << >> ║ shift ║ left to right ║
║ ║ >>> ║ ║ ║
╠═══════╬══════════════╬══════════════════════╬═════════════════╣
║ 9 ║ < <= ║ relational ║ not associative ║
║ ║ > >= ║ ║ ║
║ ║ instanceof ║ ║ ║
╠═══════╬══════════════╬══════════════════════╬═════════════════╣
║ 8 ║ == ║ equality ║ left to right ║
║ ║ != ║ ║ ║
╠═══════╬══════════════╬══════════════════════╬═════════════════╣
║ 7 ║ & ║ bitwise AND ║ left to right ║
╠═══════╬══════════════╬══════════════════════╬═════════════════╣
║ 6 ║ ^ ║ bitwise XOR ║ left to right ║
╠═══════╬══════════════╬══════════════════════╬═════════════════╣
║ 5 ║ | ║ bitwise OR ║ left to right ║
╠═══════╬══════════════╬══════════════════════╬═════════════════╣
║ 4 ║ && ║ logical AND ║ left to right ║
╠═══════╬══════════════╬══════════════════════╬═════════════════╣
║ 3 ║ || ║ logical OR ║ left to right ║
╠═══════╬══════════════╬══════════════════════╬═════════════════╣
║ 2 ║ ?: ║ ternary ║ right to left ║
╠═══════╬══════════════╬══════════════════════╬═════════════════╣
║ 1 ║ = += -= ║ assignment ║ right to left ║
║ ║ *= /= %= ║ ║ ║
║ ║ &= ^= |= ║ ║ ║
║ ║ <<= >>= >>>= ║ ║ ║
╚═══════╩══════════════╩══════════════════════╩═════════════════╝

For your specific question, this means that no extra parentheses need to be placed around the cast operation, as the precedence of the cast operator () is higher than that of the bitwise AND & operator (level 13 vs. level 7).


1 I wrote this up as a canonical answer to address questions about operator precedence and associativity in Java. I found a lot of existing answers that gave partial information, but I couldn't find one that gave an overview of the complete precedence and associativity table.

2 Operator precedence and associativiy table reproduced from https://introcs.cs.princeton.edu/java/11precedence/.

Casting reference variable without the double parentheses

You are confusing the () Parentheses in precedence 15 with the ( type ) Unary type cast in precedence 13.

The . Member selection in precedence 15 is higher than the type cast, so (B)a.b means (B) (a.b), which is why you need to write ((B) a).b to get what you want.

part of precedence table

Why have a cast in a compareTo(Object)

You are casting Object x to Task other - Object and Task are different types, so you need the cast so you can treat x as the expected type (and get to it's fields).

Normally in compareTo() you would first have something like if (x instanceof Task) before blindly casting it - if you don't and the types are different then things will crash)

C++17: What does operator with precedence below cast mean in fold concept?

The casting operator ((Typename)expr) has a very high precedence in C++'s operator precedence rules. Very few operators have higher precedence than that. Operators of cast level or greater precedence are very special operations, usually applying to a single expression.

In the expression args + ... + 1 * 2, the ... applies to everything both on the left and the right. But what does "on the right" really mean? Does it mean just the + 1 part, or does it mean + 1 * 2?

In the case of operators with high precedence, it's clear what the intent is. For example, args + ... + func(), it's clear that the () function call operator applies to func and not to args + ... + func. It's so unlikely that you would want the latter that you are forced to use parenthesis explicitly if you did ((args + ... + func)()).

However for precedence levels below 3 in the chart, things become much more cloudy for people to understand. So instead of using the normal precedence rules, C++ forces the user to be explicit about it. You can have args + ... + (1 * 2) or (args + ... + 1) * 2. But you have to be clear which one you want.



Related Topics



Leave a reply



Submit