gpt4 book ai didi

java - Ternary 和 If/Else 编译成相同的东西,为什么?

转载 作者:行者123 更新时间:2023-12-01 07:03:20 28 4
gpt4 key购买 nike

编译器将简单的三元语句编译为与编译简单的 if else 语句相同的东西吗?另外,为什么编译器要设计为以不同的方式编译它们?

例如,这样:

int a = 169;
int b = 420;
int c;
c = a > b ? 42:69;

编译为与此相同的内容:

int a = 169;
int b = 420;
int c;
if(a>b) c = 42;
else c = 69;

这个问题不是关于哪一个更好或者何时使用每一个的问题,所以请不要在您的答案中包含这一点。

最佳答案

首先,这取决于实现。 JLS 没有具体指定如何编译特定片段或操作,只要字节码在支持 Java 虚拟机规范的 VM 上运行时满足 Java 语言规范即可。不同的编译器可以生成与给出的示例不同的字节码,只要它在兼容的 JVM 上运行时给出相同的结果即可。

在 Java 8 的 javac (1.8.0_65) 上,条件运算符和 if-else 的代码不同。

三元运算符控制将哪个值压入堆栈,然后无条件存储堆栈顶部的值。在这种情况下,如果a>b,则推送42并且代码跳转到istore,否则推送59。然后顶部的任何值都会istored 到c

在 if-else 中,条件控制实际调用哪个 istore 指令。

但是请注意,在这两种情况下,指令都是“比较小于或等于”,它会跳转到 else 分支(否则继续 if 分支)。

下面可以看到各种编译器生成的字节码。您可以使用 OpenJDK JDK 中提供的 javap 工具自行获取(示例命令行 javap -c ClassName)

javac 与三元:

  public static void main(java.lang.String...);
Code:
0: sipush 169
3: istore_1
4: sipush 420
7: istore_2
8: iload_1
9: iload_2
10: if_icmple 18
13: bipush 42
15: goto 20
18: bipush 69
20: istore_3
21: return

带有 if-else 的 javac:

  public static void main(java.lang.String...);
Code:
0: sipush 169
3: istore_1
4: sipush 420
7: istore_2
8: iload_1
9: iload_2
10: if_icmple 19
13: bipush 42
15: istore_3
16: goto 22
19: bipush 69
21: istore_3
22: return
}

但是,使用ecj,代码就更加奇怪了。三元运算符有条件地推送一个或另一个值,然后弹出它以丢弃它(不存储):

Code:
0: sipush 169
3: istore_1
4: sipush 420
7: istore_2
8: iload_1
9: iload_2
10: if_icmple 18
13: bipush 42
15: goto 20
18: bipush 69
20: pop
21: return

ecj 与 if-else 以某种方式优化了推送/存储,但仍然包含一个奇怪的比较(请注意,需要保留的比较没有副作用):

Code:
0: sipush 169
3: istore_1
4: sipush 420
7: istore_2
8: iload_1
9: iload_2
10: if_icmple 13
13: return

当我添加 System.out.println(c) 来阻止此未使用值丢弃时,我发现这两个语句的结构与 javac 类似> (三元执行条件推送和固定存储,而 if-else 执行条件存储)​​。

关于java - Ternary 和 If/Else 编译成相同的东西,为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35189762/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com