2012-12-07 34 views
1

对于从字节到整数的转换,我有点困惑。请看下面的代码:将字节转换为整数时的问题(Java特定?)

byte[] data = new byte[] { 0, (byte) 0xF0 }; 

int masked = data[0] << 8 & 0xFF | data[1] & 0xFF; //240 
int notMasked = data[0] << 8 | data[1]; //-16 

因为在Java字节签署,不是240小数,而是2的补,-16。但是,它应该仍然是二进制:0x11110000那么,为什么我需要做data[1] & 0xFF

Java是否将所有内容都转换为Integer,然后将其传递给|运算符?为什么&0xFF然后呢?

+1

我前段时间做了一些代码的C到Java端口,它使用了很多按位操作,并提出了一个[helper class](https://github.com/pillingworthz/level9j/blob/master/src/java/uk /co/threeonefour/l9/vm/Conv.java)让事情变得更简单。没有关于这些质量或效率的保证,但他们为我做了这份工作。 – pauli

回答

4

Java字节被签名(不幸) - 所以当您将值提升到int以执行按位|时,它最终会被标记为0xFFFFFFF0。然后用data[0]混淆了|。用& 0xff屏蔽将其转换为240的整数值(仅为0x000000F0)。

但是,你已经有一个问题。此代码:

int masked = data[0] << 8 & 0xFF | data[1] & 0xFF; 

应该是:

int masked = ((data[0] & 0xff) << 8) | (data[1] & 0xFF); 

...否则你后掩蔽的转变,这是行不通的。我已经添加了括号,因为我从来没有肯定的&<<|的predence的...

+0

啊哈!所以'|'和'&'都被提升为整数,所以'&0xFF'在整数值*上发生。这完全解释它,非常感谢! – Miquel

+1

@Miquel:'&0xFF'确实升级为'int',所以'|'不必,如果你看到我的意思:) –

+0

后续行动:这当然是Java特定的,但是其他语言照着做? – Miquel

1

这是众所周知的类似 “拼图”

byte x = -1; 
x = x >>>= 1; 
System.out.println(x); 

产生

-1 

不换班?这是因为在编译arithemtic /移位/比较表达式之前的javac促进字节(以及短期和炭)为int或长(如果有任何长在表达),因此它的工作原理如下

x -> int = 0xFFFFFFFF; 0xFFFFFFF >>> 1 = 0x7FFFFFF; (byte)0x7FFFFFF -> 0xFF 
+0

好:)但只是没有人会感到困惑:你在这里使用带符号的移位运算符('>>>')而不是正常的运算符('>>') – Miquel

+0

好吧,我认为>>>被称为无符号的,否则没有难题,是吗? –