刷知乎的时候回答了一个提问,写在博客里记录一下
知乎地址:
java中为为什么给float类型变量赋值需要加F,而给byte、short赋值的时候却不需要呢? - 知乎 (zhihu.com)
最近刚好在看《Java虚拟机规范》,对这类提问挺感兴趣的。在查阅百度之后,我发现一篇博客
https://www.jianshu.com/p/726eef453af9
其中写道:
public class Test { public static void main(String[] args){ float f1 = 6.6f; float f2 = 1.3f; System.out.println(f1 + f2); double f3 = 6.6; double f4 = 1.3; System.out.println(f3 + f4); } }
相信不少人都会一口说出答案——两个7.9然而这个答案是错误的!!!
对于double类型和float类型,是两个完全不同的概念,相同数值的Float和Double在Java中二进制数也是不一样的。
为什么byte类型可以直接使用int赋值?
因为在Java中,byte类型是直接被编码成int类型来存储。为什么?Java就是这么设计的,我也不知道。如何得到这个结论的?我亲自通过javap -c xxx.class查看字节码 得到的。接下来上代码
public class Test{ public static void main(){ byte a = 1; a+=1; System.out.println(a); } }
JVM字节码:
Compiled from "Test.java" public class Test { public Test(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return public static void main(java.lang.String[]); Code: 0: iconst_1 1: istore_1 2: iload_1 3: iconst_1 4: iadd 5: i2b 6: istore_1 7: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream; 10: iload_1 11: invokevirtual #3 // Method java/io/PrintStream.println:(I)V 14: return }
通过查阅JVM虚拟机字节码指令表我们可知:
字节码 | 助记符 | 指令含义 |
---|---|---|
0x04 | iconst_1 | 将int型1推送至操作数栈顶 |
0x3c | istore_1 | 将操作数栈顶int型数值存入第二个本地变量表 |
iload_1 | 将第二个int型本地变量表推送至操作数栈顶 | |
0x60 | iadd | 将操作数栈顶两int型数值相加并将结果压入操作数栈顶 |
0x91 | i2b | 将操作数栈顶int型数值强制转换为byte型数值并将结果压入操作数栈顶 |
我们可以看到,在Java中存储一个byte是通过操作int的指令来完成的。所以byte与int之间可以直接进行计算操作。所以可以不用显示的声明这个byte a = 1中的1是byte类型。
什么是操作数栈,什么是本地变量表?
可以看我的博客:https://blog.mcplugin.cn/p/699