在Java中,按位AND,按位包含或问题
我在项目中有几行代码,我看不到…的价值
buffer[i] = (currentByte & 0x7F) | (currentByte & 0x80);
它从文件读取文件缓冲区,存储为字节,然后传输到缓冲区[i],如图所示,但我无法理解总体目的是什么,任何想法?
谢谢
正如其他答案已经陈述的那样, (currentByte & 0x7F) | (currentByte & 0x80)
(currentByte & 0x7F) | (currentByte & 0x80)
相当于(currentByte & 0xFF)
。 JLS3 15.22.1说这被提升为一个int
:
当运算符&,^或|的两个操作数时 是一种可转换(第5.1.8节)到基本整数类型的类型,首先对操作数执行二进制数字提升(第5.6.2节)。 按位运算符表达式的类型是操作数的提升类型。
因为JLS3 5.6.2说当currentByte
有类型byte
而0x7F
是int
(并且是这种情况),那么两个操作数都被提升为int
。
因此, buffer
将是元素类型为int
或更宽的数组。
现在,通过对int
执行& 0xFF
,我们有效地将原始byte
范围-128..127映射到无符号范围0..255,这是java.io
流经常使用的操作。
您可以在以下代码段中看到此操作。 请注意,要了解此处发生的情况,您必须知道Java将除char
之外的整数类型存储为2的补码值。
byte b = -123; int r = b; System.out.println(r + "= " + Integer.toBinaryString(r)); int r2 = b & 0xFF; System.out.println(r2 + "= " + Integer.toBinaryString(r2));
最后,对于一个真实的示例,请查看Javadoc和java.io.ByteArrayInputStream
的read
方法的实现:
/** * Reads the next byte of data from this input stream. The value * byte is returned as an
int
in the range *0
to255
. If no byte is available * because the end of the stream has been reached, the value *-1
is returned. */ public synchronized int read() { return (pos < count) ? (buf[pos++] & 0xff) : -1; }
(currentByte & 0x7F) | (currentByte & 0x80)
相当于
currentByte & (0x7F | 0x80)
等于
currentByte & 0xFF
这完全一样
currentByte
编辑:我只看了作业的右侧,我仍然认为等值是真的。
但是,似乎代码希望将有符号字节转换为更大的类型,同时将字节解释为无符号。
有没有更简单的方法将签名字节转换为java中的unsigned?
我觉得有人在这里做了太多思考。 那是不对的。
我只有一句话
- 原作者担心运行时用本机有符号整数(大概是32位)替换字节,并明确地试图告诉我们一些关于符号位是“特殊”的东西?
这是留下的代码。 除非你知道你正处于一个可疑的运行时间? 无论如何,“缓冲区”的类型是什么?
复杂的按位逻辑完全是多余的。
for (int i = 0; i < buffer.length; i++) { buffer[i] = filebuffer[currentPosition + i] & 0xff; }
做同样的事情。 如果缓冲区被声明为一个字节数组,你甚至可以省略&0xff,但不幸的是声明没有显示。
原因可能是原始开发人员对使用Java签名的字节感到困惑。
按位AND运算的结果在该位上具有1,其中两个位均为1,而按位OR运算的结果在该位上具有一个位,其中任一位为1位。
因此,值0x65的示例评估:
01100101 0x65 & 01111111 0x7F =============== 01100101 0x65 01100101 0x65 & 10000000 0x80 =============== 00000000 0x00 01100101 0x65 | 00000000 0x00 =============== 01100101 0x65
关于这些逻辑操作的好处:你可以尝试所有可能的组合(所有256个组合)并validation你得到了你期望的答案。
事实certificate,从中读取字节的文件采用带符号的位符号,并且长度不同,因此需要执行此任务以允许将其扩展为java int类型,同时保留其正确的符号:)