Java中byte做&0xff运算的原因及解析

网上瞎写的一大堆,实在是无语。把自己理解的整理分享给大家。
首先要知道原码、反码、补码是什么。可以参考:
http://www.cnblogs.com/zhangziqiu/archive/2011/03/30/ComputerCode.html

第一种情况:signed/unsigned之间的转化

java中,除了char是unsigned 两个字节,用来表达UTF-16,此外byte/short/int/long都是signed的。
取值范围:
boolean:一字节
byte:(-128,127) 一字节
char:(0,65535) 两字节
short:(-32768,32767)两字节

那么在Java与别的语言编写的程序通信时,就可能涉及到signed/unsigned之间的转化。比如C写的socket传输unsigned数据

signed到unsigned的转化

//JDK 1.8中Byte.toUnsignedInt(byte x)
public static int toUnsignedInt(byte x) {
        return ((int) x) & 0xff;//将高24位全部变成0,低8位保持不变
}

//JDK 1.8中Integer.toUnsignedLong((int x)
public static long toUnsignedLong(int x) {
        return ((long) x) & 0xffffffffL;//将高32位全部变成0,低32位保持不变
}

比较典型,经典的运用则是下面的:

//JDK1.8 ByteArrayInputStream  read函数源码

protected byte buf[];//用于缓存数据的数组

//调用该函数会返回一个(0,255)的int类型数字,如果读到stream的end,则返回-1
public synchronized int read() {
        return (pos < count) ? (buf[pos++] & 0xff) : -1;//这里跟调用toUnsignedInt(byte x)的效果是一样的
}

上面的源码可能有的人会犯迷糊
0xff的二进制是1111 1111 (8bit),一个byte也是8bit,
上面的操作buf[pos++] & 0xff是将一个byte类型的数字&0xff,那么得到的结果应该是还是这个byte类型数字本身呀?

可能你忽略了一个问题了:Java二元运算符的类型自动提升
也就是说buf[pos++] & 0xff这个运算中,buf[pos++]已经被自动提升为int了。

byte b = -20;
System.out.println(b & 0xff);// 236

final byte b2 = -20;
final byte mask = (byte) 0xff;
System.out.println(b2 & mask); // -20

第二种情况: byte转化为16进制String

在如下一段代码中有int v = src[i] & 0xFF这样的代码。

 public static String bytesToHexString(byte[] src){
        StringBuilder stringBuilder = new StringBuilder("");
        if (src == null || src.length <= 0) {
            return null;
        }
        for (int i = 0; i < src.length; i++) {
            int v = src[i] & 0xFF;
            String hv = Integer.toHexString(v);
            if (hv.length() < 2) {
                stringBuilder.append(0);
            }
            stringBuilder.append(hv);
        }
        return stringBuilder.toString();
    }

这里做&0xff的原因是:
1.byte是1byte(8位),int是4byte(32位)表示的。
2.Java中是使用了补码的形式进行数据存储的。
3.java中byte数据转化为int数据时会自动补位,如果最高位(符号位)是0,则高24位全部补0,若是1,则高24位全部补1。
4.知道了上面的三点,就有:
byte -1的二进制为(补码):1111 1111 -->对应的16进制为0xFF
int -1的二进制为(补码):1111 1111 1111 1111 1111 1111 1111 1111 -->对应的16进制为0xFFFFFFFF
5.Integer.toHexString(int i)函数内部是通过传进来数字的二进制(补码形式)来进行转换的,因此如果不进行int v = src[i] & 0xFF;
则得到的结果就是0xFFFFFFFF。而&0xff只后,传入的参数的二进制就变为0000 0000 0000 0000 0000 0000 1111 1111(虽然这个数的值以不再是-1,但是将他进行转换得到的0xff才是我们需要的)
源码如下:

//JDK1.8
static int formatUnsignedInt(int val, int shift, char[] buf, int offset, int len) {
        int charPos = len;
        int radix = 1 << shift;
        int mask = radix - 1;
        do {
            buf[offset + --charPos] = Integer.digits[val & mask];//每次do-while循环都会取4位(从高位到低位),Integer.digits[]数组是十六进制的字符集
            val >>>= shift;
        } while (val != 0 && charPos > 0);

        return charPos;
    }

final static char[] digits = {
        '0' , '1' , '2' , '3' , '4' , '5' ,
        '6' , '7' , '8' , '9' , 'a' , 'b' ,
        'c' , 'd' , 'e' , 'f' , 'g' , 'h' ,
        'i' , 'j' , 'k' , 'l' , 'm' , 'n' ,
        'o' , 'p' , 'q' , 'r' , 's' , 't' ,
        'u' , 'v' , 'w' , 'x' , 'y' , 'z'
    };

6.以上五点是全部原因,end

  • 12
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
### 回答1: 在 C 语言,int num=100; 这行代码声明了一个整型变量 num 并将其初始化为 100。 如果您想打印出 num 变量的值,可以使用 printf 函数: ``` printf("num 的值为:%d\n", num); ``` 这将在屏幕上输出: ``` num 的值为:100 ``` ### 回答2: 在C语言,int是用来声明一个整数类型的变量的关键字。在这个问题,int num = 100;语句的意思是声明一个名为num的整数变量,并将其初始化为100。 在这个语句,int表示这是一个整数类型的变量声明。num是变量的名称,在本例我们将其命名为num,你也可以选择其他任何合法的名称。=是赋值运算符,用于给变量赋初值,这里的初值是100。所以这个语句的含义是声明并初始化一个整数变量num,并将其赋值为100。 在C语言,整数变量可以用来存储整数值。在这个例子,num变量可以存储任何整数值,但是由于我们在声明变量时给其赋了初值100,所以在这个语句执行后,num变量的值就是100。 在程序,我们可以通过使用变量名num来引用这个变量,并使用它进行各种操作。比如可以对num变量进行数学运算、赋予新的值、输出等。例如,我们可以写一个打印num变量值的语句:printf("The value of num is %d\n", num);,这将输出"The value of num is 100"。 ### 回答3: 在C语言,int num=100;这行代码的作用是定义一个整型变量num,并将其赋值为100。这意味着在程序执行过程,我们可以使用变量名num来代表这个整数值100。 在这行代码,关键字int表示num是一个整型变量。整型变量是用来保存整数值的一种数据类型。num是我们给这个变量起的名字,可以按照自己的需要来命名。=是赋值运算符,用来给变量赋值。100是一个整数常量,也就是具体的数值。 通过将整数值100赋值给变量num,我们可以在程序的其他地方使用num这个变量来表示这个值。例如,我们可以使用printf函数输出num的值,使用num参与数学运算,或者将num的值赋给其他变量。 需要注意的是,在C语言,变量声明通常需要提前进行。也就是说,我们需要在使用变量之前先定义(声明)它。在这个例子,我们将变量num的定义和赋值放在了同一行,但也可以将定义和赋值分开写,比如先写int num;然后再写num=100;。 总之,这行代码的作用是定义一个整型变量num,并将其初始化为100。在程序的其他部分,我们可以使用num来表示这个整数值,进行各种操作和处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值