为了账号安全,请及时绑定邮箱和手机立即绑定

为什么4-1中的例子补0,不需要&0xff,但是用字节数组byte[i]比较的时候要&0xff

4-1 中的代码

while((b=in.read())!=-1){
    if(b<=0xf){
        //补0
        System.out.print("0");
    }

4-2

byte[] buf = new byte[20*1024];
int bytes = in.read(buf,0,buf.length);
for (int i = 0; i <bytes ; i++) {
    if((buf[i]&0xff)<=0xf){
        //补0
        System.out.print("0");
}

read方法返回的是一个字节? 这里先假设是一个字节

buf[i]同样也是字节

都是一个byte和0xf比较,为什么第一个不需要&0xff

我觉得第一个例子也是要&0xff的

今天看的一些资料:

如果read()返回的是byte的话,那就会有负数。而"返回-1意味着结束",这个信息量用byte是无法表达的,所以必须用int。

也就是b=in.read()返回的实际上是一个int型的,如果是这样的话,byte确实不用0xff

第一个问题似乎有些眉目了,但是如果是这样的话,那么第二个buf[i]又是怎么回事?

buf[i]从处理上步骤上看需要&0xff,我推测buf[i]在比较之前需要先转为int型,负数前面全补1,所以为11111111 11111111 1111111 11111111,所以需要手动做0xff处理

正在回答

5 回答

不好意思,是我没有解释清楚。这个问题提的好!

首先我们贴出Java的源码:

public synchronized int read() throws IOException {
  if (pos >= count) {
    fill();
  if (pos >= count)
    return -1;
  }
  return getBufIfOpen()[pos++] & 0xff

注意返回值,read的返回值虽然是int,但是他是读取的byte&0xff得到的,而例2中,因为直接是byte,所以老师人为的加上了这一句。

现在问题实际上就变成了为什么不能直接和0x0f比较大小,而要加上& 0xff。以-1即就是11111111自己试一试就知道了,这个之前的回答已经解释过。

根据我粗浅的理解,Java源码中& 0xff这一句避免了在读取-1时函数返回-1而错误结束的情况,实际上这时会返回225。

3 回复 有任何疑惑可以回复我~
#1

未卜先知 提问者

非常感谢你的解答,我还是没习惯看源码
2016-12-18 回复 有任何疑惑可以回复我~
#2

暮女神

感谢!
2017-03-02 回复 有任何疑惑可以回复我~

我的理解:byte型参与运算时,默认提升为int型,0xff的作用是消除前面24位,转换为0得到后面8位。read()读第一个字节时,比如1011 1101,它会提升为int型,前面补0,是整数189。read(buf,0,buf.length)读取时,假如buf[0]是读取的第一个字节,byte型的负数,但当转换为二进制时为:11111111 11111111 11111111 10111101,前面是补1的,为负数,所以用0xff消除前面24个1,转换为0,得到后八位,是整数189。具体怎么实现,需要学习底层源码。

1 回复 有任何疑惑可以回复我~

借用我另一个回答,不是很对口,但是可以解释;

凌晨来回答问题。

首先我们要弄明白,对于一个buf[i], 我们在什么情况下需要在输出之前补0,什么时候不需要补0.答案很清楚,如果它的高四位都是0,那么我们需要补,否则不需要。那么问题来了,怎么判断呢?

老师的代码是用buf[i] <= 0xf,可是代码结果不正确,会出现错误补0,也就是三个数字一起的情况。如果buf[i] == 0xff, 那么按程序是需要补0,因为作为一个byte,0xff实际上等于-1, 那么自然也小于0xf,因为0xf代表15.这就是出错的问题。

if判定语句改为((buf&oxff)<=oxf)之后,实际上结果就正确了。因为在Java中整数默认是int,也就是4个字节。因为有buf[i] & 0xff, 注意这里0xff 是4个字节的int类型,那么计算之前会把buf[i]自动进行类型转换,结果也是int类型,所以我们最终的到的结果是24位0加上原先的8位buf[i]。这时候的结果已经绝对是个正数,此时要判断buf[i]高4位是否有1,就看他和0xf的大小就行了。这里要设计一点补码的知识,我们还是以buf[i] == 0xff为例:

((buf&oxff)<=oxf)之后的结果是0x000000ff, 显然是大于0xf,所以没有补0.

实际上,我们也可以这么判断:buf[i] & 0xf0 == 0;这样的结果会保留buf[i]的高四位,其他位都是0,比较容易理解。


0 回复 有任何疑惑可以回复我~
#1

未卜先知 提问者

其实你还是没回答核心问题,第一个方法,read方法读到的是一个字节,假设是-1(当然这里用-1来假设不是太好) 第二个方法,buf[i]里面存的也是一个字节,假设读到的也是-1,这两个按道理说存的是一样的东西,为什么一个需要0xff,一个不需要0xff
2016-12-15 回复 有任何疑惑可以回复我~

我觉得都可以,可能只是讲解者随意了

0 回复 有任何疑惑可以回复我~

因为while啊 

0 回复 有任何疑惑可以回复我~

举报

0/150
提交
取消

为什么4-1中的例子补0,不需要&0xff,但是用字节数组byte[i]比较的时候要&0xff

我要回答 关注问题
意见反馈 帮助中心 APP下载
官方微信