java 位操作入门

最近有涉及的网络编程方面的工作,对java的位操作算是入门了!
    /**
     * The default byte order of bytes: BIG_ENDIAN
     * 
     * @param bytes
     * @return
     */
    public static final int getUnsignedInt(byte... bytes) {
        switch (bytes.length) {
            case 1:
                return 0xFF & bytes[0];
            case 2:
                return ((0xFF & bytes[0]) << 8) | (0xFF & bytes[1]);
            case 3:
                return ((0xFF & bytes[0]) << 16) | ((0xFF & bytes[1]) << 8) | (0xFF & bytes[2]);
            case 4: {
                int i = ((0xFF & bytes[0]) << 24) | ((0xFF & bytes[1]) << 16) | ((0xFF & bytes[2]) << 8)
                        | (0xFF & bytes[3]);
                if (i > 0)
                    return i;
            }
        }
        throw new RuntimeException("over the max value");
    }

以上代码,隐藏了如下知识点:
1. java中,使用补码的形式来表示二进制的:
  a). 正数的原码、反码和补码是一样的;
  b). 负数的补码有如下规则:原码——>反码——>补码
      原码:负数的原码为1|x|
      反码:负数的反码,符号位不变,数值取反
      补码:负数的反码加1(会影响符号位)
2. java中进行算术和位运算时
  a). 整数存储时,使用的是big-endian字节序列: 高字节在前,低字节在后
  b). 类型会自动按精度从“低”到“高”进行转换,转换的顺序如下:
      byte——>short——>int——>long——>float——>double
  c). 位运算后,byte,short都转换了int类型
// 值为2,这里赋值的就是用的补码形式
int i2 =0x02;
// 值为-2,这里赋值的就是用的补码形式
int i_2 = 0xFFFFFFFE;
        byte b1 = (byte) 0x01;
        byte b_1 = (byte) 0xFF;
        byte b_2 = (byte) 0xFe;
        System.out.println("b_1: " + b_1);
        System.out.println("0x0FF & b_1: " + (0x0FF & b_1));
        
        // -2的补码进行左移后,得到是-256。由于负数补码与原码不一样,因此左移操作后,高位也会发生了变化,再转换成原码计算出的数值就不是预期的 。
        System.out.println("b_1 << 8: " + (b_1 << 8));
        // 终于明白0xFF&的作用了:使用0xFF&是为了确保负整数的高位不变,即为0x000000FF&
        System.out.println("(0xFF & b_1) << 8: " + ((0xFF & b_1) << 8));
        // 但如果操作是正数,则不用0xFF来保证高位不变,是因为正数的补码与原码是一样的,左移操作后,除了低位左移了指定位数外,补码其它高位并没有变化(即都是0)
        System.out.println("b1 << 8 : " + (b1 << 8));

        // 把-1这个数值强制转换成了int型
        int i_1 = b_1;
        System.out.println(i_1 << 8);

你可能感兴趣的:(java)