int转byte和位运算问题

前言

在 Java 中 int 占 4 个字节, short 占 2 个字节, byte 占 1 个字节,有时候我们需要将 int 转换为 byte 就需要舍弃一些高位或者低位数据。

转换

比如有两个变量:

int i = 5;
int j = 0xff24;
int k = -4;
int m = -400;
System.out.println(Integer.toBinaryString(i));
System.out.println(Integer.toBinaryString(j));
System.out.println(Integer.toBinaryString(k));

二进制补码表示:

0000 0000 0000 0000 0000 0000 0000 0101 (5的补码)
0000 0000 0000 0000 1111 1111 0010 0100 (0xff24的补码)

0000 0000 0000 0000 0000 0000 0000 0100 (-4 的 绝对值)
1111 1111 1111 1111 1111 1111 1111 1100 (-4 的 补码)

0000 0000 0000 0000 0000 0001 1001 0000 (-400 的 绝对值)
1111 1111 1111 1111 1111 1110 0111 0000 (-400 的 补码)

我们先强转一下:

byte bi = (byte)i;
byte bj = (byte)j;
byte bk = (byte)k;
System.out.println(byteToBit(bi));
System.out.println(byteToBit(bj));
System.out.println(byteToBit(bk));

public static String byteToBit(byte b) {
    return ""
            + (byte) ((b >> 7) & 0x1) + (byte) ((b >> 6) & 0x1)
            + (byte) ((b >> 5) & 0x1) + (byte) ((b >> 4) & 0x1)
            + (byte) ((b >> 3) & 0x1) + (byte) ((b >> 2) & 0x1)
            + (byte) ((b >> 1) & 0x1) + (byte) ((b >> 0) & 0x1);
}

二进制补码表示:

00000101 (正常)
00100100 (截取低8位)
11111100 (正常)
01110000 (截取低8位,成了正数112)

所以由此得出一个结论,如果要使用int强转位byte类型,如果 int 存储的值在 -128 到 127 之间则转换后值一致,如果超出这个范围则会改变正常的值。

如果是将一个byte数据转换为int则比较简单,直接补位,因为 int 的长度大于 byte.

按字节取出

public static byte[] intToByte(int val){
    byte[] b = new byte[4];
    b[0] = (byte)(val & 0xff);
    b[1] = (byte)((val >> 8) & 0xff);
    b[2] = (byte)((val >> 16) & 0xff);
    b[3] = (byte)((val >> 24) & 0xff);
    return b;
}

假设我们定义了一个字节的前4位表示x的值,后4位表示y的值,如何将两个个int类型的坐标转换为一个byte类型。

int ix = 10;
int iy = 8;
System.out.println(Integer.toBinaryString(ix));
System.out.println(Integer.toBinaryString(iy));
byte xy = (byte)((byte)(ix << 4) + (byte)iy);
System.out.println(byteToBit(xy));

控制台输出二进制形式:

0000 0000 0000 0000 0000 0000 0000 1010
0000 0000 0000 0000 0000 0000 0000 1000
10101000

有时候我们需要将 4 个字节 byte 转换为一个 int 转换代码如下:

public static int byte2int(byte[] data, int n) {
    switch (n) {
    case 1:
        return (int) data[0];
    case 2:
        return (int) (data[0] & 0xff) | (data[1] << 8 & 0xff00);
    case 3:
        return (int) (data[0] & 0xff) | (data[1] << 8 & 0xff00) | (data[2] << 16 & 0xff0000);
    case 4:
        return (int) (data[0] & 0xff) | (data[1] << 8 & 0xff00) | (data[2] << 16 & 0xff0000)
                | (data[3] << 24 & 0xff000000);
    default:
        return 0;
    }
}

附测试代码

public class Test {

    public static void main(String[] args){

        System.out.println("########### int二进制形式 ############");
        int i = 5;
        int j = 0xff24;
        int k = -4;
        int m = -400;
        System.out.println(Integer.toBinaryString(i));
        System.out.println(Integer.toBinaryString(j));
        System.out.println(Integer.toBinaryString(k));
        System.out.println(Integer.toBinaryString(m));

        System.out.println("########### byte二进制形式 ############");
        byte bi = (byte)i;
        byte bj = (byte)j;
        byte bk = (byte)k;
        byte bm = (byte)m;
        System.out.println(byteToBit(bi));
        System.out.println(byteToBit(bj));
        System.out.println(byteToBit(bk));
        System.out.println(byteToBit(bm));

        System.out.println("########### x,y坐标转byte ############");
        int ix = 10;
        int iy = 8;
        System.out.println(Integer.toBinaryString(ix));
        System.out.println(Integer.toBinaryString(iy));
        byte xy = (byte)((byte)(ix << 4) + (byte)iy);
        System.out.println(byteToBit(xy));
    }

    /**
     * 按位拼接字符串
     * @param b
     * @return
     */
    public static String byteToBit(byte b) {
        return ""
                + (byte) ((b >> 7) & 0x1) + (byte) ((b >> 6) & 0x1)
                + (byte) ((b >> 5) & 0x1) + (byte) ((b >> 4) & 0x1)
                + (byte) ((b >> 3) & 0x1) + (byte) ((b >> 2) & 0x1)
                + (byte) ((b >> 1) & 0x1) + (byte) ((b >> 0) & 0x1);
    }

    /**
     * 按字节取出
     * @param val
     * @return
     */
    public static byte[] intToByte(int val){
        byte[] b = new byte[4];
        b[0] = (byte)(val & 0xff);
        b[1] = (byte)((val >> 8) & 0xff);
        b[2] = (byte)((val >> 16) & 0xff);
        b[3] = (byte)((val >> 24) & 0xff);
        return b;
    }
}