面试官:字节流中的read()方法是读取一个字节,那为什么返回值是int型?

面试过程中可能会遇到面试官问这个问题:

字节流中的read()方法是读取一个字节,那为什么返回值是int型?今天来简单说一下

首先看下JDK文档

可以看到文档对read方法的描述都是返回一个字节的数据,但是它的返回的却是int型,那这是为什么呢?

而且InputStream类里的read( )是一个抽象的方法,这是一个模板方法模式,InputStream类里写好 流操作的大体逻辑,但是read()这个方法等着子类去实现,那咱们就看下InputStream的一个子类 BufferedInputStream 类里具体实现的read( )方法

可以看到最后它返回的时候& 0xff 也就是32位的255,这是为什么呢?

是因为在读一个文件的时候有可能会遇到读到连续8个1的情况,而8个1的十进制正好是-1,这就和结束标志那个-1冲突了,就会出现有可能还没读完但是由于你返回-1了导致结束了。

那么这个怎么解决呢?
现在有个解决方案,那就是让每次读到的一个字节8位的数据都提升成int型的,那11111111提升完了变成 11111111 11111111 11111111 11111111,不还是-1吗?还是-1,是因为提升成32位的时候前边是补的1导致的,那让前边补成0不就可以了?那怎么才能让前边补0而不是补1呢?&上int型的255,&完int的255后,得到的是00000000 00000000 00000000 11111111,这个数就不是-1了,这样既能让最后的8位保持原来一个字节8位的数据,而且还可以避免出现-1的情况。

举个例子:00000001   这是1,这个数的负数 是原数取反+1,即 11111110+1  -----> 11111111

所以把8位的-1(也就是00000001) 提升成32位的时候,

就成了 0000000 00000000 00000000 00000001取反 -----> 1111111  11111111   11111111  11111110

再加1 ----->1111111  11111111   11111111  11111111

所以一个byte的-1 也就是11111111 提升成int型的-1就成了1111111  11111111   11111111  11111111,这个不还是-1吗?

这个是因为提升了以后,前边的24位是补了1,那如果前24位补0的话,就既避免了等于-1的情况,又可以把原来的数据保留在最后8位,那怎么才能让前24位补0呢?
大家都知道1是true,0是false,所以这时候再&与上0000000 00000000 00000000 11111111也就是32位的255

1111111  11111111   11111111  11111111      -1
&
0000000 00000000 00000000 11111111    255
--------------------------------------------------------------------
0000000 00000000 00000000 11111111

所以这么做完以后,既避免了等于-1的情况,又可以把原来的数据保留在最后8位。

就算读到了11111111也不怕和结束标识-1冲突了,因为最后的结果是0000000 00000000 00000000 11111111

这个数根本不是-1。所以冲突问题解决,最关键的是,冲突问题解决的同时,提升完的这个数据的最后8位还保留了之前的数据的原样。
所以咱们可以总结一下:为了避免遇到读到连续8个1的情况,read方法在做提升,把读取到的byte转换成int,而且返回的数据是&上int型255,这样做既能避免-1出现,又能让返回的int型数据的最后8位保留的是原数据,但是由于read把读取的数据做了提升,真正有效的数据只有最后8位,那所以wtite方法写的时候就需要把最后一个字节8位的数据写出去就行了,如果不这么做的话,那写完以后文件的大小将是读取过来文件大小的4倍,所以read是在做提升,write是在做强转(只要最后8位,其他高位上的0全抛弃)

最后有一个小技巧:如果要想只保留最后8位就&上255,要想只保留后4位就&上16

  • 9
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

嗑嗑嗑瓜子的猫

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

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

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

打赏作者

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

抵扣说明:

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

余额充值