Java 按什么顺序计算这个特定的表达式:System.out.println("g."+ " big " + 2*3);
In which order does Java evaluate this particular expression : System.out.println("g."+ " big " + 2*3);
Is 2*3 first evaluated 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 to 阅读对了。
System.out.println("g."+ " big " + 2*3);
最终输出为g。 big 6,但我更关心它的求值顺序
这不是重复的,因为它不关注字符串和整数的 + 操作。问题是 '*' 是否最后完成,因为它出现在 '+' 之后,当从(左到右)读取表达式时可以很容易地执行。
在java中,*
运算符的优先级高于+
运算符。这导致语句被评估为以下
第一步2 * 3 = 6
第二步"g."+ " big " = "g. big "
第三步"g. big " + 6 = "g. big 6"
您可以阅读有关 java 运算符顺序的更多信息 here
我想规范说 'appears to be' 因为有些情况,例如您发布的情况,如果不检查代码就无法真正分辨。整个表达式可以,我希望是,在编译时求值。
这与优先级无关;优先级决定了操作数是什么,而不是计算顺序。因此 *
的操作数是 2
和 3
,而不是 g.big2
和 3
。
有点不同以避免编译器做太多事情
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());
}
输出:
a b c d 016
和反汇编代码:
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
尽管操作数是按从左到右的顺序计算的,但先进行乘法,然后进行串联。
这里是问题的反汇编代码:
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
确认 and ,编译器将整个操作简化为一个字符串"g. big 6"
使用 int 变量 (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
Is 2*3 first evaluated 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 to 阅读对了。
System.out.println("g."+ " big " + 2*3);
最终输出为g。 big 6,但我更关心它的求值顺序
这不是重复的,因为它不关注字符串和整数的 + 操作。问题是 '*' 是否最后完成,因为它出现在 '+' 之后,当从(左到右)读取表达式时可以很容易地执行。
在java中,*
运算符的优先级高于+
运算符。这导致语句被评估为以下
第一步2 * 3 = 6
第二步"g."+ " big " = "g. big "
第三步"g. big " + 6 = "g. big 6"
您可以阅读有关 java 运算符顺序的更多信息 here
我想规范说 'appears to be' 因为有些情况,例如您发布的情况,如果不检查代码就无法真正分辨。整个表达式可以,我希望是,在编译时求值。
这与优先级无关;优先级决定了操作数是什么,而不是计算顺序。因此 *
的操作数是 2
和 3
,而不是 g.big2
和 3
。
有点不同以避免编译器做太多事情
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());
}
输出:
a b c d 016
和反汇编代码:
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
尽管操作数是按从左到右的顺序计算的,但先进行乘法,然后进行串联。
这里是问题的反汇编代码:
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
确认"g. big 6"
使用 int 变量 (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