Java整型数据与常量池

众所周知,Java会自动将字符串字面量(如"hello")放到常量池中,但作为整型字面量是否会被放到常量池中呢?下面进行实验
实验环境为:Java 1.8.0_212

实验一
public class Test{
	public static void main(String[] args){
		// 整型最大值
		int i1 = 0x80000000;  
		int i2 = 1;
	}
}

编译源码得到Test.class后,通过javap -verbose Test.class查看常量池信息:
在这里插入图片描述
从图中红色方框中,可以看到只有 0x80000000 被放入到了常量池,而 1 没有被放入到常量池。同样是以字面量写入到源代码中的,为什么会出现这种不一致现象呢?

猜想一下

0x800000001 的唯一区别是值的大小不同,会不会是Java编译器在编译时,以某个值作为阀值,将大于该值的整型字面量放入到常量池中,而小于该阀值的整型字面量就不放入到常量池中呢?下面用实验进行验证

实验二
public static void main(String[] args) {
    	// 单字节(byte)最大值
		int i1 = 0b0111_1110;
		// 单字节最小值
		int i2 = -0b1000_0000;

		// 双字节(char、short)最大值
		int i3 = 0b0111_1111_1111_1111;
		// 双字节最小值
		int i4 = -32768;

		// 四字节(int)最大值
		int i5 = 0x7fff_ffff;
		// 四字节最小值
		int i6 = 0x8000_0000;
    }

在这里插入图片描述
从图中红色方框中,可以看到只有字面量 0x7fffffff0x8000_0000 被放入到了常量池。再结合代码逻辑可以推断出,区间(0b0111_1111_1111_1111,0x7fffffff]、[0x7fffffff,-32768)应该可以被放到常量池中,换句话说只要一个整型字面量要用2个字节以上进行存储,就会被放到常量池

实验三
public class Test {
    public static void main(String[] args) {
	    // Short.MAX_VALUE + 1
		int i3 = 0b1000_0000_0000_0000; 
		// Short.MIN_VALUE - 1
		int i4 = -32769; 
	}
}

编译源码得到Test.class后,通过javap -verbose Test.class查看常量池信息:
在这里插入图片描述
可以看到猜想得到了验证。

探究本质原因

为什么只有两个字节以上的整型变量才会被放入到常量池中呢?因为Java字节码指令只提供了

  • iconst_n(1 <= n <=5)将1到5的整数放入到Java虚拟机栈中的操作数栈中;
  • bipush PARAM 将-128到127的整数(一字节数)放入到Java虚拟机栈中的操作数栈中;
  • sipush PARAM 将 -32769到32768的整数(两字节数)放入到Java虚拟机栈中的操作数栈中;
    而对于超过三字节数进行表示的数无法通过指令的方式将其放到操作数栈中,所以在编译时期把它放到了常量池中。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值