java怎样把一个类的boolean类型返回的值赋值另一个类_「JVM」原始类型 boolean 在 JVM 中的讨论...

导言

在开始学习JVM字节码之后,遇到了一个有意思的问题,下面这段代码,会输出什么:

public class Foo {

public static void main(String[] args) {

boolean flag = true;

if (flag) {

System.out.print("A");

}

if (flag == true) {

System.out.print("B");

}

}

}

这个问题的答案很显然——会输出AB。

接下来重点来了,如果将 2 赋值给flag变量,会输出什么呢?如果将flag赋值为 3 呢?

要知道这两个问题的答案,我们得知道在JVM中boolean类型的变量是如何表示的,以及在这两个if语句中到底进行了怎样的判断。

boolean 类型在 JVM 中是如何表示的

在命令行中输入javap -c Foo,得到反编译的字节码如下:

Compiled from "Foo.java"

public class geektime.part1.Foo {

public geektime.part1.Foo();

Code:

0: aload_0

1: invokespecial #1 // Method java/lang/Object."":()V

4: return

public static void main(java.lang.String[]);

Code:

0: iconst_1

1: istore_1

2: iload_1

3: ifeq 14

6: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;

9: ldc #3 // String Hello, Java!

11: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V

14: iload_1

15: iconst_1

16: if_icmpne 27

19: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;

22: ldc #5 // String Hello, JVM!

24: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V

27: return

}

在字节码文件的main方法中,第0~2行完成了将一个int类型的常量赋值给了第一个变量flag的操作。于是我们得到了结论:

在JVM中boolean类型的变量是用数字 0 和 1 来表示的。false用 0 表示,true用 1 表示。

if (flag) 分析

然后继续看字节码文件,接下来的字节码就是代表第一个判断语句if (flag) 语句,从3~11行都属于第一个if代码块,首先是ifeq。

080fced4b389654763d02c1a5f2a7464.png

ifeq助记符的作用是:当栈顶 int 型数值等于0时跳转。这里跳转的意思就是不执行语句块中的代码。

此时的栈顶 int 型数值就是刚刚被赋值给 flag 的1,所以在这里ifeq 14的意思就是当 flag 等于 0 的时候跳转到14行,由于第14已经不属于 if 语句的范围了,所以这里的跳转是不执行 if 语句的意思。也就是说,if(flag)中是判断 flag 的值,当 flag 值不等于0的时候才执行 if 中的语句。

if (flag == true) 分析

接下来继续看第二个判断语句if (flag == true)语句,是在字节码的14~24行。前面两行是将一个int类型的数值1和flag变量推送到栈顶,可以理解为把接下来将要进行比较的true放入将要进行比较的一个“容器”,然后是if_icmpne助记符。

e69aaa5dbbf0f65cb53364dfdb4ffe0f.png

if_icmpne助记符的作用是:比较栈顶两int型数值大小,当结果不相等时跳转。

现在栈顶两int型的数值是刚刚推送的true也就是1,以及flag变量,所以if_icmpne助记符是比较这两个数值,如果他们相等,执行if语句的内容。也就是说,if(flag == true)中是进行flag和true的判断,当它们相等时执行if中的语句。

为什么编译器提示可以简化

关于上述的示例代码,编译器或许会在第二个if语句提醒你可以Simplify,当你执行简化以后你会发现它将if (flag == true)变成了if (flag),如下图所示。

e69688a473297dcbdb35435c6fddfd0b.png

在没有Simplify之前,这两个 if 语句如果要执行,第一个的条件是 flag 不等0,第二个的条件是 flag 等于1。这是两个完全不同的比较嘛!但是为什么在编译器中可以画上等号呢?

000e2ae5d5faf17e6c498a9fa08db438.png

当我们已经了解过boolean类型的变量在虚拟机中的表现形式之后,答案显而易见。首先这里的flag是一个boolean类型的变量,它只有true和false两种值,即在虚拟机中只有0和1两种值。所以对于一个boolean类型的变量,不等0就代表了它一定等1,所以编译器才会发出可以简化的提示。

如果将 flag 的值赋为其他整数型值

我们知道在正常情况下编译器不会接受将2这一个数字赋值给boolean类型变量的这么一个操作,但是我们可以通过一些其他的工具(如asmtools)来实现这个操作。

将flag的值赋为2。在字节码中就是将iconst_2赋值给flag时,输出为空。

将flag的值赋为3。在字节码中就是将iconst_3赋值给flag时,输出为AB。

如果再多做几个实验,将flag的值赋为4,输出为空;将flag的值赋为5,输出为AB......

如果我们将这些整数都转化为二进制,即2=0010,3=0011,4=0100,5=0101。

当二进制末尾为0时,无输出,当二进制末尾为1时,输出AB。

由此我们可以得出结论:如果将其他整数类型的值赋值给一个boolean类型的变量,虚拟机会取此整数值二进制的最后一位。

总结

boolean类型的变量在虚拟机中有两种表现形式:true用1表示,false用0表示。

当虚拟机执行if(boolean)的条件判断时,实际进行的判断是该布尔值是否不等于0,当该布尔值不等于0时执行if语句中的内容。

当虚拟机执行if(boolean==true)的条件判断时,实际进行的判断时该布尔值是否等于1,当该布尔值等于1时执行if语句中的内容。

编译器提示if(boolean==true)可以简化为if(boolean)的原因是在虚拟机中布尔值只有两种值,执行不等于0的判断与执行等于1的判断是等价的。

若在虚拟机中将其他int值赋值给一个布尔类型的变量,虚拟机会取此整数值二进制的最后一位。

b739ec46bb5c46d9c0aa4ce35ba1ea56.png

关于找一找教程网

本站文章仅代表作者观点,不代表本站立场,所有文章非营利性免费分享。

本站提供了软件编程、网站开发技术、服务器运维、人工智能等等IT技术文章,希望广大程序员努力学习,让我们用科技改变世界。

[「JVM」原始类型 boolean 在 JVM 中的讨论]http://www.zyiz.net/tech/detail-136650.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值