[知乎回答] Java中为为什么给float类型变量赋值需要加F,而给byte、short赋值的时候却不需要呢?

刷知乎的时候回答了一个提问,写在博客里记录一下

知乎地址:
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虚拟机字节码指令表我们可知:

字节码助记符指令含义
0x04iconst_1将int型1推送至操作数栈顶
0x3cistore_1将操作数栈顶int型数值存入第二个本地变量表
iload_1将第二个int型本地变量表推送至操作数栈顶
0x60iadd将操作数栈顶两int型数值相加并将结果压入操作数栈顶
0x91i2b将操作数栈顶int型数值强制转换为byte型数值并将结果压入操作数栈顶

我们可以看到,在Java中存储一个byte是通过操作int的指令来完成的。所以byte与int之间可以直接进行计算操作。所以可以不用显示的声明这个byte a = 1中的1是byte类型。


什么是操作数栈,什么是本地变量表?

可以看我的博客:https://blog.mcplugin.cn/p/699

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注

Captcha Code