Given an expression f1() + f2()*f3()
with 3 method calls, java evaluates (operands of) addition operation first:
int result = f1() + f2()*f3();
f1 working
f2 working
f3 working
I (wrongly) expected f2()
to be called first, then f3()
, and finally f1()
. Because multiplication shall be evaluated before addition.
So, I don't understand JLS here - what am I missing?
15.7.3. Evaluation Respects Parentheses and Precedence
The Java programming language respects the order of evaluation indicated explicitly by parentheses and implicitly by operator precedence.
How exactly operator precedence is respected in this example?
JLS mentions some exceptions in 15.7.5. Evaluation Order for Other Expressions (method invocation expressions (§15.12.4),method reference expressions (§15.13.3)), but I cannot apply any of those exceptions to my example.
I understand that JLS guarantees that operands of a binary operation are evaluated left-to-right. But in my example in order to understand method invocation sequence it is necessary to understand which operation (and both its operands respectively!) is considered first. Am I wrong here - why?
More examples:
int result = f1() + f2()*f3() + f4() + f5()*f6() + (f7()+f8());
proudly produces:
f1 working
f2 working
f3 working
f4 working
f5 working
f6 working
f7 working
f8 working
Which is 100% left-to-right, totally regardless of operator precedence.
int result = f1() + f2() + f3()*f4();
produces:
f1 working
f2 working
f3 working
f4 working
Here the compiler had two options:
f1()+f2()
- addition first f3()*f4()
- multiplication first But the "evaluate-left-to-right rule" works here as a charm!
This link implies that in such examples method calls are always evaluated left-to-right regardless of any parenthesis and associativity rules.
You're missing the text immediately under 15.7:
The Java programming language guarantees that the operands of operators appear to be evaluated in a specific evaluation order, namely, from left to right.
The values of the operands of an expression are evaluated before the expression itself. In your specific case, The outermost expression is f1() + [f2() * f3()]
. We must first evaluate f1()
, then we must evaluate f2() * f3()
. Within that, f2()
is evaluated first, then f3()
, then the multiplication (which returns the value for the operand of the +
).
JLS §15.17.2. Evaluate Operands before Operation:
The Java programming language guarantees that every operand of an operator (except the conditional operators
&&
,||
, and?
:
) appears to be fully evaluated before any part of
the operation itself is performed.
Thus, f1()
, f2()
and f3()
are evaluated first (left-to-right). Then, operator precedence is applied.
After all, you could observe the execution order in the bytecode, which in my case is:
[...]
INVOKESTATIC Main.f1 ()I
INVOKESTATIC Main.f2 ()I
INVOKESTATIC Main.f3 ()I
IMUL
IADD
Here is how the Expression Tree would look like:
+
/ \
/ \
f1 *
/ \
/ \
f2 f3
Leaves are evaluated first and the operator precedence is encoded in the tree itself.
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