基本数据类型转换及溢出问题
1. int(Integer)和long(Long)之间的转换
- int转long:向上转换,可直接进行隐形转换
int a = 10;
long b = (int)a;
int a = 10;
long b = a.longValue();
- long转int:向下转换(容量大的数据类型转为容量小),可能会出现数据溢出情况
long a = 10;
int b = (int)a;
long a = 10;
int b=a.intValue();
2.基本数据类型的取值范围
数据类型 | 占位大小 | 存储数据量 | 最大值 | 最小值 |
---|---|---|---|---|
byte | 8 | 2^8-1 = 255 | 2^7-1 = 127 (0111,1111) | -2^7 = -128 |
short | 16 | 2^16-1 = 65535 | 2^15-1 = 32767 | -2^15 = -32768 |
int | 32 | 2^32-1 | 2^31-1 = 2147483647 | -2^31 |
long | 64 | 2^64-1 | 2^63-1 | -2^63 |
byte类型的最小值为什么是-128而非-127?
原因:计算机表示数值的方法有:原码、反码、补码,而现在计算机用补码存储整数数值
- 原码:用二进制表示的原始编码
- 反码:除了符号位外,其它位取反
- 补码:正数的补码等于原码、负数的补码等于反码加1
而byte的最大正数为二进制的01111111 = 2^7-1 = 127 (0为符号位),这没有问题
对于负数而言,补码等于反码加1
- 1111,1111 补码就是 1000,0001 = -1
- 1111,1110的补码就是 1000,0010 = -2
- 依次类推…
- 1000,0001的补码就是 1111,1111 = -127
- 接下去 最大负数为 1000,0000 (十进制为 -0,但是就与+0重复,没有意义)不是负数的话,补码仍为 1000,0000,计算机就将这一数值表示为最大负数 -128
3.几个Demo
public class demo1{
public static void main(String[]args){
byte num=127;
num+=2;
//输出是-127,原理是因为byte类型是8位的数据
System.out.println(num);
}
}
分析:127 对应的二进制为 0111,1111,其补码仍为:0111,1111,(计算机中只有加法运算,且运算都是其补码运算!!!)
加上2之后-------> 补码是:1000,0001(加1为“1000,0000”再加1为“1000,0001”)
上述补码再转回原码为:1111,1111 就是 -127
注意:当数据类型为byte、short、char型时,相互之间不能转换,它们参与运算是先将数据转换为int类型进行运算,也就是说若demo中num为byte类型的数据的话,是不会出现错误情况的!
public class demo1{
public static void main(String[]args){
Int num1=2147483647;
Int num2=2147483647;
//输出是-2,原因是int容器太小,溢出
System.out.println(num1+num2);
}
}
分析:本来结果是 4294967294,因为int 之间的结果 还是int类型
4294967294的二进制及其补码都是 “1111,1111,1111,1111,1111,1111,1111,1110”转换为补码就是“1000,0000,0000,0000,0000,0000,0000,0010”
十进制结果就是 -2
4.int转为byte类型的溢出处理
byte的存储范围是-128-127的整数范围,byte a = (byte)130;结果会是多少呢?java是如何处理强制类型转换的溢出处理呢?
- 在计算机中,所有数据都以补码形式存储,那么130首先当作int存储,32位,其二进制原码和补码都为:“0000,0000,0000,0000,0000,0000,1000,0010”;
- 转换为byte类型,进行截取,高字节部分去除,保留低字节部分(即留取后面部分),得到转换为byte的补码为:“1000,0010”
- 转回原码为:“1000,0010”—>“1000,0001”------>“1111,1110” 十进制表示“-126”
所以高容量向下转换存在数据溢出的情况