在阅读java源代码时会经常发些代码里面会出现诸如byte & 0xFF之类的代码,之前没深究,感觉是多此一举的操作。
后经过仔细研究发现里面涉及底层数据存储基本原则正数存储的二进制原码,负数存储的是二进制的补码。
在netty源码中,会使用Bytebuf来接收网络数据。如明确知道是一个字节无符号的数字,会调用ByteBuf.readUnsignedByte方法获取该字节的内容
public short readUnsignedByte() {
return (short) (readByte() & 0xFF);
}
复制代码
其中readByte()会返回该字节对应的byte,但为什么后面有和 0xFF 进行按位与操作然后转换为short呢。
首先netty在接收网络数据时,会以相应大小的容器进行接收。当读取这一个字节的内容时会保存到byte类型中。但java的byte是一个有符号的数据类型,正数存储的二进制原码,负数存储的是二进制的补码,补码是负数的绝对值的反码再加1。当最高位为1时,如直接读取该byte,java会把该byte当成一个负数。为了正确的显示该数据,需要把byte转换成short,并确保高8位都是0。所以需要和0xFF进行按位与操作。
public static void main( String[] args ){
byte b=(byte) 0b11110011; //模拟通过byte接收一个字节长度的无符号的数据(补码表示为-13即byte,但实际我们想表示的是243) 11110011
System.out.println( b );
System.out.println( (short)b );
System.out.println( (short) (b & 0xFF) ); //在使用是需要通过先 & 0xFF,然后转换成大类型
}
复制代码
输入为:
-13
-13
243
复制代码