• 在Java中,对 byte 和 short 类型 进行位操作的时候,严重留意事项


    参考:https://www.cnblogs.com/yongdaimi/p/5899362.html

    ============================================================

    总结:在java中,对byte和short类型的 右移操作 必须先进行 & 0xff 后再右移,避免byte或short是负数的情况下,导致 右移操作前 自动升为int,前面补了很多1,此时右移会把1冲到高位上,从而错误;

    int 和  long没有任何问题;

    左移没有这个问题,因为左移及时自动转换成int 在前面补了很多1后,后面的截断 还是会把左边的都截掉,就是说 左移 永远是从右边补0,而右移由于自动转换成int的存在,会导致即使使用了>>>的情况下

    左边还是会补1,因为负数转换成int的时候,前面的每一位都是1了。留意。

    ((bytes[0] & 0xff) >>> 3);

    1.举例:

        public static void main(String[] args) {
            byte[] bytes = new byte[1];
            bytes[0] = 31;//00011111
            bytes[0] <<= 3;//11111000
            bytes[0] >>>= 3;// 这步很诡异的变成了 11111111 ????
            System.out.println(bytes[0]);// -1;最终的结果为-1???
        }

    接下来调试看下:

     

     

    导致输出的结果为-1,而不是31的原因是,在java中 对byte和 short进行位操作的话,会先默认自动转换为int 再进行位操作;

        public static void main(String[] args) {
            byte[] bytes = new byte[1];
            bytes[0] = 31;//00011111
            /*
             bytes[0] <<= 3;这步发生的情况如下:
             0000 0000 0000 0000 0000 0000 0001 1111(先把byte[0]转换成int)
             0000 0000 0000 0000 0000 0000 1111 1000(再左移3位)
             1111 1000(再赋值给byte[0],截断)
             */
            bytes[0] <<= 3;
    
            /*
             bytes[0] >>>= 3; 又发生了什么:
             1111 1111 1111 1111 1111 1111 1111 1000(把当前的byte[0]转换成int,由于是负数,所以转换成了这样,左边按符号位全部补1,就是由这步自动转换导致了问题,解决方法就是把这步自动转换前面的1去除,用 & 0xff)
             0001 1111 1111 1111 1111 1111 1111 1111(右移3位)
             1111 1111(赋值截断,最终 byte[0]的值,可见变成全是1了)
             */
            bytes[0] >>>= 3;
    
    
            /*
             输出byte[0]发生了什么,输出byte[0]就是把byte[0]的值转换成10进制,计算机发现byte[0]的最高位是1,说明是负数,
             计算机认为它是负数后,负数在计算机中是以补码的方式来存储的,所以具体的10进制的值是它的原码,需要把补码转换成原码
             规则:1.补码符号位不变,其余位取反;
                  2.取反后加1,就是原码
                  1000 0000(符号位不变,其余位取反)   
                  1000 0001(取反后加1,就是原码) 
                  原码就是具体的值,可见是-1
             */
            System.out.println(bytes[0]);
        }

    解决方法,系统自动把byte[0]由byte自动向int 转换后的值再与0xff取与运算,使其一个字节的前面的位全部为0:

    1111 1000 --> 1111 1111 1111 1111 1111 1111 1111 1000(自动向int转换)

    然后我们再通过& 0xff 让它们取与运算:

    1111 1111 1111 1111 1111 1111 1111 1000

    0000 0000 0000 0000 0000 0000 1111 1111

    =

    0000 0000 0000 0000 0000 0000 1111 1000(这个才是我们想要的)

    与&0xff 运算后,再说右移的事,就解决了这个问题;

    总结:在java中,操作byte右移前一定要先 &0xff 做与运算,才能右移;

        public static void main(String[] args) {
            byte[] bytes = new byte[1];
            bytes[0] = 31;//00011111
            bytes[0] <<= 3;
            bytes[0] = (byte) ((bytes[0] & 0xff) >>> 3);
            System.out.println(bytes[0]);
        }

    ==================================================================================================================

    接下来看下short:

    看下 int :

    看下long:

  • 相关阅读:
    积跬步,聚小流------关于UML类图
    深度学习 Deep Learning UFLDL 最新 Tutorial 学习笔记 1:Linear Regression
    数字语音信号处理学习笔记——语音信号的短时频域分析(2)
    PHP程序猿必须学习的第二课——站点安全问题预防
    Connection for controluser as defined in your configuration failed.
    NYOJ 76 超级台阶
    单片机小白学步系列(十) 单片机程序下载相关知识
    SQL 语言划分
    UVA 11754
    客户端远程方法声明
  • 原文地址:https://www.cnblogs.com/del88/p/15839209.html
Copyright © 2020-2023  润新知