-1

Is 2*3 evaluated first because * has higher precedence or is "g."+ " big " evaluated to "g. big " before evaluating 2*3 to 6, as the expression is read from left to right.

System.out.println("g."+ " big " + 2*3);

The final output is g. big 6, but I am more concerned about the order in which it is evaluated.

This is not duplicate as it doesn't focus on the + operation on strings and integers. The question is whether '*' is done at last, since it is present after a '+' that can be performed readily when the expression is read from (left to right).

GBlodgett
  • 12,704
  • 4
  • 31
  • 45
Svel04
  • 149
  • 10
  • PEMDAS: https://en.wikipedia.org/wiki/Order_of_operations – rdas Oct 01 '19 at 22:48
  • 2
    Possible duplicate of [Java '+' operator between Arithmetic Add & String concatenation?](https://stackoverflow.com/questions/38352779/java-operator-between-arithmetic-add-string-concatenation) – tevemadar Oct 01 '19 at 22:52
  • Nit: ```println``` sees a single string argument; the argument is evaluated before ```println``` is entered. –  Oct 01 '19 at 22:53
  • 2
    @Marvin [No](https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.7). Precedence determines what the operands are, not the evaluation order. Thus the operands of ```*``` are ```2``` and ```3```, not ```g.big2``` and ```3```. –  Oct 01 '19 at 22:59
  • 1
    This is not duplicate as it doesn't focus on + operation on strings and integers. The question is wether * is done at last, since it is present before a + that can be performed readily as it reads from left to right. – Svel04 Oct 01 '19 at 23:06
  • @Marvin another-dave already showed you what the "implicitly" in your quote means, Java respects the fact that `*` has the operands "2" and "3", not "g.big2", thus implicitly giving `*` a higher precedence by not concatenating "g.big" and "2" as it should due to the evaluation order. – Tom Oct 01 '19 at 23:09
  • 1
    I see. Although I'm not sure if the compiler wouldn't simplify it to `"g.big " + 2*3` anyway ;) – Marvin Oct 01 '19 at 23:25
  • It could even evaluate the whole thing to "g.big 6" compile time. –  Oct 01 '19 at 23:29
  • I guess I should turn my comment to an answer. –  Oct 01 '19 at 23:43

3 Answers3

1

In java, the * operator has higher precedence than the + operator. This leads the statement to be evaluated as the following

step one 2 * 3 = 6

step two "g."+ " big " = "g. big "

step three "g. big " + 6 = "g. big 6"

you can read more about the order of java operators here

Ryan
  • 1,972
  • 2
  • 23
  • 36
  • 2
    Precedence is not [evaluation order](https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.7). –  Oct 01 '19 at 23:00
1

Evaluation is apparently left to right.

I suppose the specification says 'appears to be' because there are cases, such as the one you posted, where you can't really tell without examining code. The whole expression could be, and I would hope is, evaluated at compile time.

This is independent of precedence; precedence determines what the operands are, not the evaluation order. Thus the operands of * are 2 and 3, not g.big2 and 3.

1

A little bit different to avoid compiler doing too much

static String a() { System.out.print("a "); return "0"; }
static String b() { System.out.print("b "); return "1"; }
static int c() { System.out.print("c "); return 2; }
static int d() { System.out.print("d "); return 3; }

public static void main(String... args) {
    System.out.println(a() + b() + c() * d());
}

output:

a b c d 016

and the disassembled code:

public static void main(java.lang.String...);
  Code:
     0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
     3: invokestatic  #10                 // Method a:()Ljava/lang/String;
     6: invokestatic  #11                 // Method b:()Ljava/lang/String;
     9: invokestatic  #12                 // Method c:()I
    12: invokestatic  #13                 // Method d:()I
    15: imul
    16: invokedynamic #14,  0             // InvokeDynamic #0:makeConcatWithConstants:(Ljava/lang/String;Ljava/lang/String;I)Ljava/lang/String;
    21: invokevirtual #15                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
    24: return

despite the operands being evaluated in left-to-right order, the multiplication is done first, the concatenation next.


Here the disassembled code from question:

System.out.println("g."+ " big " + 2*3);
  Code:
     0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
     3: ldc           #16                 // String g. big 6
     5: invokevirtual #15                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V

confirms another-dave's answer and comment, the compiler simplified the whole operations to one string "g. big 6"


With int variables (0:a, 1:b, 2:c, 3:d):

System.out.println(a + b + c * d);
  Code:
    12: iload_0
    13: iload_1
    14: iadd
    15: iload_2
    16: iload_3
    17: imul
    18: iadd
    19: invokevirtual #21                 // Method java/io/PrintStream.println:(I)V
user85421
  • 28,957
  • 10
  • 64
  • 87
  • maybe a *better* question, regarding order of execution, would be what happens if all four operands were variables of type `int` (no optimization; no concatenation with 3 elements) {add, multiply, add} – user85421 Oct 02 '19 at 00:24
  • My guess is that the specification's words "appear to be" come into play here. Without inspecting the code, how can you tell what the actual order is? –  Oct 02 '19 at 00:29
  • maybe by the [JLS 19. Syntax](https://docs.oracle.com/javase/specs/jls/se13/html/jls-19.html). `AdditiveExpression: MultiplicativeExpression | AdditiveExpression + MultiplicativeExpression` and `MultiplicativeExpression: UnaryExpression | MultiplicativeExpression * UnaryExpression` (is just another description for (or consequence of) "left operand first" and "operands before operation") {but now it's late for good thinking} – user85421 Oct 02 '19 at 00:40