Integer的特性

int 类型是java中常见的基本类型。但是最近我发现在int的使用有一些不易掌握的特性,在不深入了解内部原理情况下,容易判断错误。
1、Integer 真是引用类型吗
众所周知,Integer作为int包装类是引用类型。但是请看下面这段代码,最后输出是true。

Integer a=127;
Integer b=127;
System.out.println(a==b);

2、-2147483648
在数学意义上,绝对值是非负数。但下面代码取绝对值的输出还是-2147483648

     int tmp=Math.abs(-2147483648);
     System.out.println(tmp);

以上问题涉及两个知识点

  1. IntegerCache
  2. 计算机加减法运算(原码、反码、补码)

把两个知识点展开看
- IntegerCache
JSL规定IntegerCache为Integer类的缓存类,默认缓存了-128~127的Integer 值,如遇到[-128,127]范围的值需要转换为Integer时会直接从IntegerCache中获取。同时,我们可以通过设置java.lang.Integer.IntegerCache.high来设置缓存最大值
-Djava.lang.Integer.IntegerCache.high=255

- 计算机加减法(原码、反码、补码)

  • 原码、反码和补码
    我们都知道计算机中的数值使用二进制表示的,与计算机存储结构有关。假定我们的计算机为4位机(一个Byte),那么十进制1在转为二进制就是0001。此外,我们还需要考虑一个问题那就是符合,负数我们怎么表示,我们将第一位设置为符号位(0为正数+,1为负数-)。这样我们的原码就出来了。
十进制4位二进制原码
10001
-21010

考虑到计算机特性,运算方式越简单越好。我们考虑将减法转换成加法,这就引入了反码。正数的反码还是正数,负数的反码是除符号位外,全部取反。一个二进制数(原码)减去另一个二进制数(原码)就转换为一个二进制数反码加上另一个二进制数的反码。

十进制原码反码
100010001
-110001111
二进制结果1000
十进制结果-0
十进制原码反码
100010001
-210101101
二进制结果1110
二进制结果求反1001
十进制结果-1

如上图所示反码的引入,虽然解决了加法变减法的转换,却引入负零和循环进位等复杂计算逻辑。
补码的出现则进一步简化了运算,补码只需要进行简单加法,舍弃进位即可得到结果。

十进制原码反码补码
1000100010001
-2101011011110
二进制结果1111
二进制结果反码1110
二制结果1001(-1)
  • Integer的边界问题
    通过引入补码,计算机的加减运算简化为了简单的相加,数值在计算机内存中也以补码的形式存储。
    原码 => 补码: 取反加一(符号位不参加运算)
    补码=> 原码: 取反加一(一般情况下,符号位不参加运算)
    在补码中,1000不再表示负零,而是-8。所以给定n位存储长度,可以表达数值范围为-2的n次方到2的(n-1)次方。

由补码求其绝对值补码的公式为,补码取反加一(包括符号位)

以下为给定4位长度的二进制数求绝对值。

十进制原码补码其绝对值原码
-1100111110001
-8100010001000

-2147483648为int 给定32位最小的值,与-8类似,绝对值与其本身一致。

最后总结

在计算机数值计算时,需要考虑数值精度是否一致和是否有溢出。

  1. 数值超过数据类型支持最大精度溢出后,计算结果出错(不仅仅是丢失进度)
  2. 数值计算,结果精度就最大的精度
  3. Integer计算需要考虑是否有缓存
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值