Java中丢失精度的窄化强制类型转换
显示类型转换
Java的8中基本类型中,值域大的向值域小的转换需要使用强制转型.
转型结果会丢失精度,那么到底是如何转的?
Short转 Byte之正数
//数在计算机底层保存的是反码
//原码构造一个2字节的short类型数
short a = b2s("0000 0001 0101 1010");
byte a_b = (byte) a;
System.out.println(a_b);
System.out.println(Integer.toBinaryString(a_b));
//因为a是正数,所以补码等于原码
//a的补码为
// "0000 0001 0101 1010"
//向下转型时,丢失精度,这里丢弃高位1字节
// "0101 1010"
//补码转原码为(最高位是符号位;正数不变;负数取反加1;)
// "0101 1010" 正数,最高位0
byte b = +0b1011010;//正数
System.out.println(b);
assertEquals(a_b, b);
90
1011010
90
Short转 Byte之负数
//数在计算机底层保存的是补码,其最高为是符号位
//原码构造一个2字节的short类型数,注意这个的第8位为1
short a = b2s("0000 0001 1101 1010");
byte a_b = (byte) a;
System.out.println(a_b);
System.out.println(Integer.toBinaryString(a_b));
//因为a是正数,所以补码等于原码
//a的补码为
// "0000 0001 1101 1010"
//向下转型时,丢失精度,这里丢弃高位1字节
// "1101 1010"
//补码转原码为(最高位是符号位;正数不变;负数取反加1;)
// "1010 0101" 负数,最高位1,其他位取反
// "1010 0110" 加1
byte b = -0b0100110;//负数
System.out.println(b);
assertEquals(a_b, b);
-38
11111111111111111111111111011010
-38
Int转 Short 1
//Short转Byte之正数
int a = b2i("0000 0000 0000 0001 0000 0001 0000 1111");
short a_b = (short) a;
short b = +0b100001111;
System.out.println(b);
assertEquals(a_b, b);
271
Int转 Short 2
//参见Short转Byte之负数
int a = b2i("0000 0000 0000 0001 1000 0001 0000 1111");
short a_b = (short) a;
short b = -0b111111011110001;
System.out.println(b);
assertEquals(a_b, b);
-32497
Short转 Byte 1
//参见Short转Byte之负数
short a = b2s("0000 0001 1111 1111");
byte a_b = (byte) a;
byte b = -0b1;
System.out.println(b);
assertEquals(a_b, b);
-1
Short转 Byte 2
//Short转Byte之正数
short a = b2s("0000 0001 0000 0000");
byte a_b = (byte) a;
byte b = +0b0;
System.out.println(b);
assertEquals(a_b, b);
0
其他类型转 Boolean 使用 Unsafe操作
Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
Unsafe unsafe = (Unsafe) field.get(null);
final long valueOffset = unsafe.objectFieldOffset
(ForceTypeConvert.class.getDeclaredField("value"));
//这个比较特殊
//int,short,byte转boolean都只取最低位,1->true,0->false
unsafe.putByte(this, valueOffset, (byte) 2);
assertEquals(value(), false);
unsafe.putByte(this, valueOffset, (byte) 3);
assertEquals(value(), true);
unsafe.putLong(this, valueOffset, 99999L);
assertEquals(value(), true);