挖掘& 0xFF深层的含义

本文详细探讨了Java中通过`&0xFF`操作将有符号字节转换为无符号整数的过程。文章首先介绍了原码、补码和反码的概念,然后解释了为什么需要进行这种转换,因为Java中的`byte`类型是有符号的,可能会导致负数的误读。作者通过实例展示了如何通过位运算实现转换,并指出该操作在`BufferedInputStream`类中的应用。最后,总结指出`&0xFF`是实现有符号到无符号转换的关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


前言

int unsignedbyte = b & 0xFF;

上面的这段代码相信会较为容易的经常看到,但是我们往往会忽略为什么要这样,不这样行不行。接下来就此段代码,挖掘它的深层的含义。


一、前置知识?

1.原码,补码,反码

定义那些我在这儿就不在赘述了,我分享一下我的理解。
众所周知,冯诺依曼体系结构的计算机的一大特点就是

数据以二进制表示

这里的数据,不仅指文件数据,是计算机使用的一切数据,包括程序员编写的程序编译后的代码数据。直观上理解二进制,和十进制不同的是十进制是满十进一,而二进制是满二进一,所以二进制数据只包含0、1。如上,理解原码,反码,补码,我们也可以和我们熟悉的十进制来进行对比理解。
我们十进制数据中有正负之分,二进制数据也有。二进制数据怎么表示呢?这里有两派,一个是主张使用一个位置存放符号,这个缺点很明显,会导致存储密度下降。还有一派就是这里采用的原码表示正数,补码表示负数。(正数的原码和补码是一样的,所以计算机数据严格来说是用补码表示的)。首先明白一个道理,一个数的负数是什么?引用古代数学名著《九章算术》的话

两算得失相反,要令正负以名之

所以这里的意思就是说加起来等于零,就是这个数的负数。
所以用这里的知识,就能不用符号位表示二进制数据中的正负。
首先,没有了符号位(无符号数)默认为正数
比如十进制数(110)
bin:0110 1110
反码:就是逐位取反,结果就是原数和它的反码之前的和为oxFF
而补码就是反码加一,这里加一的意思就是使得原数和补码之间的和为0,这里的0是数据溢出代表的0

二、挖掘& 0xFF深层的含义

byte[] bytes = new byte[4];
//从当前文件指针读取4个字节的数据
imageBis.read(bytes,0,4);

从这里我们就获取到了四个字节的数据,那么我们可以直接用这四个字节的数据吗?答案是否定的!
我们之前理解到了,计算机内部数据存储用的是补码,而byte这个数据结构是有符号数,所以如果首位是一,它就会读取为负数,如果是零,它就会读为正数。
举个例子
bin 1001 0110
如果用byte读取就会表示有符号数-22,它实际表示的是无符号数150
知道了问题产生的原因,怎么实现转化呢?答案就是下面的代码:

首先在java中int是表示四个字节,所以上面的例子在运算之前会转化为四个字节的数据,高位补1

//oxFFFFFF96 & 0xFF = 0x96
//高位被&0截取了,只留了低位一个字节的有效数据0x96
int unsignedbyte = b & 0xFF;

到这里就应该挖掘结束了。

总结

& 0xFF实际上就是实现有符号数向无符号数之间的转换。
//截取了JDK BufferedInputStream类中的read方法说明 & 0xff的正确性
class:BufferedInputStream
public synchronized int read() throws IOException {
        if (pos >= count) {
            fill();
            if (pos >= count)
                return -1;
        }
        return getBufIfOpen()[pos++] & 0xff;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

来日可期1314

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值