Search code examples
javaundefined-behaviorassignment-operatorevaluationmethod-call

Evaluation order between a method call and arguments in Java


Dealing with another SO question, I was wondering if the code below has an undefined behavior:

if (str.equals(str = getAnotherString())) {
  // [...]
}

I tend to think the str reference from which the equals() call is made is evaluated before the further str assignment passed as argument. Is there a source about it?


Solution

  • This is clearly specified in the JLS Section 15.12.4:

    At run time, method invocation requires five steps. First, a target reference may be computed. Second, the argument expressions are evaluated. [...]

    What's a "target reference" you ask? This is specified in the next subsection:

    15.12.4.1. Compute Target Reference (If Necessary)

    ...

    • If form is ExpressionName . [TypeArguments] Identifier, then:
      • If the invocation mode is static, then there is no target reference. The ExpressionName is evaluated, but the result is then discarded.
      • Otherwise, the target reference is the value denoted by ExpressionName.

    So the "target reference" is the str bit in str.equals - the expression on which you are calling the method.

    As the first quote says, the target reference is evaluated first, then the arguments. Therefore, str.equals(str = getAnotherString()) only evaluates to true if getAnotherString returns a string that has the same characters as str before the assignment expression.

    So yeah, the thing that you tend to think is correct. But this is not "undefined behaviour".