java 中的三元运算符 - 从编译器和 jvm 的角度来看不理解

Ternary operator in java - not understandin from compiler and jvm perspective

提问人:Boris Hartiník 提问时间:11/10/2023 最后编辑:Boris Hartiník 更新时间:11/10/2023 访问量:70

问:

我理解正确吗

字节 b =40;

编译器类型检查值是否属于数据类型(字节)范围内 OK,然后JVM分配内存并保留该值?

如果我没记错的话,我的戏剧在这里是三元运算符

字节 A = 10<20?30:40;

编译器知道数据类型和值常量,因此编译器将进行比较并将值分配给变量“a”??所以在这种情况下 jvm 不分配内存?

第二个例子

int a =30,b=20;

字节 c=(a<b)?10:20;

编译器不知道值 a,b 只对 datatypes(int) 第一行进行类型检查,

第二行编译器知道值 10 和 20,但比较将由 JVM 完成(JVM 知道值?因此,JVM 来进行比较并将数字 10 和 20 提升为 int 类型??,因此该数字不能分配给字节变量?...我不知道我在哪里理解为什么数字 20(false) 不能分配给字节......

谢谢

解释运行时编译器类型检查和 jvm 的问题

Java JVM 编译器构造

评论

2赞 Stephen C 11/10/2023
每当使用原始类型进行计算时,JVM 都不会分配内存。基元值保存在寄存器和堆栈中,以及某些对象的字段中。在这方面,三元运算符没有什么特别之处。假设您使用的是基元类型(如示例中所示),则不会分配内存。
2赞 Stephen C 11/10/2023
“解释运行时编译器类型检查和 jvm 的问题”——这个问题太宽泛了。
1赞 Stephen C 11/10/2023
对于该示例,您需要知道的是,您可以使用类型转换来使其工作;即 (如果你真的想理解“为什么”,你需要能够阅读JLS。而且你没有足够的技术知识......还。事实上,大多数 Java 程序员从来没有走得那么远。byte c = (byte) ((a < b) ? 10 : 20);
1赞 Stephen C 11/10/2023
为了给你一个问题的字面答案:编译器知道 and 是值,它知道 和 是变量(不是)。1020intabintfinal
3赞 Holger 11/10/2023
不应将编译器和 JVM 的内存管理混为一谈。JVM 是完全无关紧要的。编译器遵循严格的规则。只有当变量的值是编译时常量且在字节值范围内时,才能将值赋给变量。在所有其他情况下,这是不允许的,无论正确性对人类读者来说多么明显。例如,当你有 时,你不能这样做,因为它不在上述规则的涵盖范围内。intbytevoid foo(byte b) {}foo(10);

答:

-1赞 Reilas 11/10/2023 #1

'...编译器类型检查值是否属于数据类型(字节)范围内 OK,然后JVM分配内存并保留该值?...'

40 是一个 int 文字,因此编译器将评估声明的数据类型是否可以包含它。

换言之,以下内容将无法编译。

byte b =1234;

'...编译器知道数据类型和值常量,因此编译器将进行比较并将值分配给变量“a”??所以在这种情况下 jvm 不分配内存?...'

它只会为一个字节分配内存,前提是您提供的值可以适应边界。

这意味着,以下内容将编译。

byte a = 10<20?30:1234;

'...编译器不知道值 a,b 只做类型检查 datatypes(int)-first line ...

。我不知道我在哪里理解为什么数字 20(false) 不能分配给字节......”

解释器不会走得太深。
我想如果你提供一个动态值,它不会评估任何东西。

或者,您可以将 ab 声明为最终值,尽管我不确定这有多实用。

final int a =30,b=20;

byte c= (a<b)?10:20;

评论

3赞 Stephen C 11/10/2023
“口译员不会走得太深。我想,如果你提供一个动态值,它不会评估任何东西。- 实际上,这一切都在 JLS 中指定。这不是编译器(或解释器)是否可以实现它的问题。(任何一个都可以......但他们不允许......
2赞 Holger 11/10/2023
分配内存可能意味着不同的事情,具体取决于您正在查看的内容。此外,目前尚不清楚 OP 是否引用了局部变量或字段。仅在创建实例时分配的字段的内存。另一方面,局部变量的内存是在线程启动时分配的,这就是为什么如果堆栈对于您的代码来说太小,您最终可能会遇到错误(除非 JVM 支持堆栈扩展,这与 HotSpot 不同)。此外,对于局部变量,例如,、或的编译代码是相同的。int i = 40;byte b = 40;char c = '(';