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);

引用

posted @ 2020-05-09 17:36  onion94  阅读(613)  评论(0编辑  收藏  举报