Operator precedence and associativity in Java
A programming language has rules that determine precisely how an expression is decomposed into subexpressions. By “decomposing into subexpressions” we mean how we could group subexpressions by surrounding them with parentheses. E.g., expression 1 + 2 * 3
could be grouped into subexpressions as follows:(1 + (2 * 3))
, which shows that 2 * 3
is a subexpression (but 1 + 2
is not).
Understanding how to decompose expressions is particularly important for expressions that contain multiple operators (like 1 - 2 * 3
).
Some languages (like WeScheme) require that you make the structure of the expression explicit by always using parentheses. Other languages (like Pyret) require parentheses only where expressions otherwise would be ambiguous. Most languages, though, have a set of rules that determine how parenthesis-less expressions are to be decomposed.
Operator Precedence and Associativity
The rules that govern the decomposition are called precedence rules and associativity rules. The precedence rules distinguish between different kinds of operators (where a higher precedence means the operators are grouped into subexpressions earlier). The associativity rules distinguish whether operators of the same precedence should be grouped into subexpressions from left to right or from right to left.
The following expression contains no operator. So we don't have to worry about the decomposition:
15
The following expression contains one single operator. So we also don't need to worry in which order operators get evaluated. (However, we might have to worry whether and in which order the operands of the operator are evaluated! That aspect, however, is not part of the operator precedence or associativity rules!)
width * height
The following expression contains two operators with different precedence:
2 * width + height
Let's assume the expression is written in the Java programming language. Given that in Java the multiplication operator (*) has higher precedence (12) than the addition operator (+, 11), Java first evaluates the multiplication, and then uses the result of the multiplication to evaluate the addition.
The following expression contains two operators of the same precedence:
12 - 1 + 9
The associativity of these operators is left-to-right. Thus, first Java computes 12 - 1 = 11
, and then 11 + 9 = 20
. (If the associativity was right-to-left, then it would first compute 1 + 9 = 10
, and then 12 - 10 = 2
. That would lead to a different result!)
Operator Precedence and Associativity in Java
The following table shows, from highest (what happens first) to lowest (what happens last), the precedence of the operators in Java. It also shows their associativity.
Precedence | Operator | Kind | Associativity |
---|---|---|---|
15 | () [] · | Parentheses Array subscript Member selection | Left to Right |
14 | ++ -- | Unary post-increment Unary post-decrement | (not associative) |
13 | ++ -- + - ! ~ ( type ) | Unary pre-increment Unary pre-decrement Unary plus Unary minus Unary logical negation Unary bitwise complement Unary type cast | Right to left |
12 | * / % | Multiplication Division Modulus | Left to right |
11 | + - | Addition Subtraction | Left to right |
10 | << >> >>> | Bitwise left shift Bitwise right shift with sign extension Bitwise right shift with zero extension | Left to right |
9 | < <= > >= instanceof | Relational less than Relational less than or equal Relational greater than Relational greater than or equal Type comparison (objects only) | (not associative) |
8 | == != | Relational is equal to Relational is not equal to | Left to right |
7 | & | Bitwise AND | Left to right |
6 | ^ | Bitwise exclusive OR | Left to right |
5 | | | Bitwise inclusive OR | Left to right |
4 | && | Logical AND | Left to right |
3 | || | Logical OR | Left to right |
2 | ? : | Ternary conditional | Right to left |
1 | = += -= *= /= %= | Assignment Addition assignment Subtraction assignment Multiplication assignment Division assignment Modulus assignment | Right to left |
Most Java programmers do not memorize this entire table! But they at least understand the precedence and associativity of the basic arithmetic operators (+, -, *, /) one learns in school. And they are able to use the table so they can evaluate or type-check expressions, and so they can properly break an expression into subexpressions.
Examples: Indicating Subexpression Structure with Parentheses
In the following examples we show an expression and then rewrite that expression by adding extra (unnecessary) parentheses. The parentheses show the structure of the expression (how the expression is broken into subexpressions). This is like the tree structure discussed in our “Expression Trees”.
Addition and Subtraction Operators
In this first example, all operators have the same precedence (11).
These operators (+
and -
) are left-associative (they group left-to-right). Thus,
a + b - c + d
means
(((a + b) - c) + d)
Equality Operators
The two equality operators (==
and !=
) have the same precedence (8).
They are left-associative (they group left-to-right). Thus,
a == b != c == d
means
(((a == b) != c) == d)
Note: what would the type of c
and d
have to be for this expression to type-check?
Assignment Operators
The various assignment operators have the same precedence (1).
They are right-associative (they group right-to-left). Thus,
a = b += c = d
means
(a = (b += (c = d)))
Note: Using assignment operators in subexpressions is not necessarily good style. Some programmers use them when they want to set multiple variables in one statement (x = y = 0;
). However, assignments have side effects (they change the value of a variable) and thus using them deep inside an expression can be confusing and should usually be avoided.
Conditional Operator
The ternary conditional operator is right-associative (it groups right-to-left). Thus,
a ? b : c ? d : e
means
(a ? b : (c ? d : e))