基本数据类型转换
在Java中,我们经常使用到基本数据的类型转换,类型转换用来将一个数值从一种类型转换位另一种类型。
我们都直到对于基本数据类型,在内存中都会占有不同的大小,如下
数据类型 | 位数(字节) |
---|---|
char |
16位(2字节) |
byte |
8位(1字节) |
short |
16位(2字节) |
int |
32位(4字节) |
long |
64位(8字节) |
float |
32位(4字节) |
double |
64位(8字节) |
boolean |
8位(1字节) |
在基本数据的类型转换中分为两种,一种是强制(显式)类型转换,一种是自动(隐式)类型转换。
首先要声明一下,在Java中所有写的数字字面量,对于整数都是int
类型的,比如:1000
,这就是一个int
类型的数字字面量;对于小数都是double
类型的,比如:2.22
,这就是一个double
类型的数字字面量。
强制类型转换指的是数值范围较大的数据类型变量转换为数值范围较小的数据类型变量,这样有可能会造成精度的损失。这种转换,在编程时需要我们显示的声明,例如:
int i = 22;
//对于变量,由于我们有时不能确定变量的具体值,所以需要一直进行显示的声明类型转换
byte a = (byte)i;
//对于数字字面量,如果其值没有超出目标数据类型的数值范围,则不需要显示的声明类型转换
//如果其值超出了目标数据类型的数值范围,则需要显示的声明类型转换,这是就会产生精度的损失
byte b = 22;
byte c = (byte)220;
自动类型转换值得是数值范围较小的数据类型自动转换位数值范围较大的数据类型,比如:
byte b = 1;
int i = b;//此时就不需要显示的声明类型转换
但是对于从范围较小的整型类型转换位范围较大的整型类型时有个规定:如果最初的值的数值类型是有符号的,那么就执行符号扩展;如果最初的值是char
类型的,那么不管它将要转换成什么类型的数据,都执行零扩展。那么什么叫符号扩展,什么叫零扩展呢?
符号扩展:二进制中的有符号数,符号位总是位于数的第一位,如果向方位较大的数据类型进行扩展,符号位也应该位于第一位才对,所以当一个负数被扩展时,其扩展的高位全被置位为1;对于整数,因为符号位是0,所以其扩展的位仍然是0。
零扩展:不管要转换成什么整型类型,不要最初值的符号位是什么,扩展的高位都被置位0.
下面看这样一个输出:
public static void main(String[] args){
System.out.println((int)(char)(byte)-1);
}
也许你会认为不管怎么样,该程序都会输出-1
.当当运行后,该程序 却输出了65535
,这是为什么?实际上这就关系到了我们上面提到的符号扩展。
对于字面量-1
,它是一个int类型的数据,由于计算机中对于负数采用二进制补码来表示,二进制表示为1111 1111 1111 1111 1111 1111 1111 1111
,int
类型转换为byte
类型,对数据进行窄化,其高24位全部被丢弃,转换后的数据仍然是-1
,二进制表示为1111 1111
,这没有错。
当byte
类型转换位char
类型时,是对数据进行拓宽数位,但不可能将一个负byte
值转换为char
类型。所以实际上从byte
到char
的类型转换时是先将byte
转换为int
类型,然后再将int
类型转换为char
类型。简单地根据上面介绍的规则,byte
转换为char
发生符号扩展,拓展的高位全部置为1,char
类型没有有符号与无符号之分,所以转换后的char
表示的数据是65535
。
但是当char
类型转换位int
类型,从16位拓宽到32位,由于最初数值是char
类型的,所以不管转换成什么类型的数据类型,都会执行零扩展,所以转换为作为结果的int
类型数据是65535
。
如果你的程序中运用到了上面的规则,那么你应该很清楚地标识出来。
二进制补码:计算机中用二进制补码表示负数,对二进制数取反,然后加
1
。比如说-3
,表示位16位二进制,首先将3
表示为二进制0000 0000 0000 0011
,然后对其取反得到1111 1111 1111 1100
,然后在加1,得到1111 1111 1111 1101
表示的-3
的二进制补码形式.
如果有错误的地方,请指正。
网友评论