关于JAVA中Byte数据类型二进制赋值运算报错问题
自从 JDK7 更新之后,新增了二进制变量的表示, 支持将整数类型用二进制来表示,用 0b 开头;
例如: byte b= (byte) 0b1000_0001;
short s = (short) 0b1000_0000_0000_0001;
新手在这个时候会遇到一个问题,为啥 byte b=0b100_00001 会报错(cannot convert from int to byte)
而 short b=0b100_00001 又不会呢?既然 java 底层默认 0b100_00001 是 int 类型,为什么 short 可以呢?
有的人说是 byte 是字节数据类型,short 是短整数据类型,个人认为不太准确。所以我们在做个试验:
试验 1:short b=0b100_00001;// 正常赋值;
short s=0b1000_0000_0000_0001;// 系统报错(cannot convert from int to byte);
这个结果出来想必大家都有些眉目了,在二进制中最高位被定义为符号位,byte 共有 8 个比特位,我们给它
0b0000_0001 时,最高位0系统无法判断是 实际数值 还是 符号位数值 。如果我们加上(byte),则系统认为
此时的 0 是符号位,可以赋值;如果没有加(byte),则认为是实际数值,然而 byte 类型只有 8 个比特位,无位置
表示符号位,因此溢出报错。
试验 2:byte b=0b0000_0001;// 正常赋值
byte b=0b1000_0000;// 报错
再次印证了上面的推理,默认最高位是实际数值,超出位宽报错。
----------------------------------------------------------------- 黄金分割线 ---------------------------------------------------------------------
问题 2:
byte a=(byte)0b1111_1111+0b0000_0001; ---> 0 // 运行结果为 0
有人解释道 0b0000_0001 为 int 类型,而 (byte)0b1111_1111 为 byte 类型,运算时会转为 int 类型运算,即为:
0000_0000_0000_0000_0000_0000_1111_1111
+
0000_0000_0000_0000_0000_0000_0000_0001
||
0000_0000_0000_0000_0000_0001_0000_0000
|| 转为 byte 类型,直接截取后 8 位
0000_0000 = 0
那么又有人问了:
int a=(byte)0b1111_1111+0b0000_0001; 0 // 运行结果同样为 0,为什么不是 256
按照上面的意思被赋值变量 a 属于 int 类型,既然是按照 int 类型运算,结果就不用转换了嘛,直接赋值不就行啦?
我们在看几组试验:
1 、 byte a=(byte)0b0000_0001+0b1111_1111; --> 报错 //cannot convert from int to byte
int a=(byte)0b0000_0001+0b1111_1111; -->256 正常赋值
2 、 byte a=(byte)0b1111_1111+(byte)0b0000_0001; --> 0
int a=(byte)0b1111_1111+(byte)0b0000_0001; --> 0
3、 byte a=(byte)(0b1111_1111+0b0000_0001); --> 0
int a=(byte)(0b1111_1111+0b0000_0001); --> 0
4、 int a=0b1111_1111+0b0000_0001; --> 256
第一组报错从第一个问题可以推出,0b1111_1111 超出了等号左边的 byte 类型范围,所以才会报错。
我们有三种推断:
第一、如果是都转为 byte 类型进行运算,那会考虑到符号位,多余正溢出,超出位宽自然舍弃,相加结果应为 0b1000_0000,结果应为 -128 才对
显然结果不是这样的,因此这种推断错误;
第二、如果是都转为 int 类型进行运算,然后把值赋值给等号左边,这种推论试验 2 中 int a=0,说不通,因此这种推断错误;
第三、运算按照 java 直接值得规则,数值类型进行算数运算时,所有参与算数运算的数都会自动转换为参与运算的最大类型,得到的值也是该类型
我们一一验证补码运算的结果 {(byte)0b1111_1111 对应的原码为 1000_0001 即为 -1,而 0000_0001 位 1,相加结果为 0},以上问题都可以推理出来,
因此,第三种推论是正确的,打完收工。