byte取值范围_Java中byte做&0xff运算的原因及解析

全网最全1500份Java学习资料、500份BAT面试真题:

                       关注公众号,输入“面试题”,获取提取码!

第一种情况: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,则返回-1public 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);// 236final 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才是我们需要的)
源码如下:

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'    };

以上五点是全部原因。

·END·

c6435563e40b63478f5fd38112ec30a3.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值