关于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},以上问题都可以推理出来,

因此,第三种推论是正确的,打完收工。

 

posted @ 2019-04-03 18:50  强壮的野人之歌  阅读(2168)  评论(0编辑  收藏  举报