Java 为什么bit或操作将导致符号扩展,而bit和won';T

Java 为什么bit或操作将导致符号扩展,而bit和won';T,java,bit-manipulation,Java,Bit Manipulation,我需要在Java中将一个字节强制转换为int,但我不想要符号扩展,所以我这样做了 byte b = -1 (int) (b & 0xF) // this returns 15, which is what I want (int) (b | 0) // this returns -1, which is essentially 0xFFFF, sign extension happens, not what I want 我认为上面两个应该给出相同的结果,但事实并非如此。 我必须在

我需要在Java中将一个字节强制转换为int,但我不想要符号扩展,所以我这样做了

byte b = -1
(int) (b & 0xF) // this returns 15, which is what I want
(int) (b | 0)   // this returns -1, which is essentially 0xFFFF, sign extension happens, not what I want
我认为上面两个应该给出相同的结果,但事实并非如此。
我必须在位运算中漏掉一些东西。

诀窍是打印这些值的二进制表示,并对它们执行二进制运算

byte b = -1;
int a = (int) (b & 0xF); // this returns 15, which is what I want
int c = (int) (b | 0); // this returns -1, which is essentially 0xFFFF
System.out.println("b:" + Integer.toBinaryString(b));
System.out.println("a:" + Integer.toBinaryString(a));
System.out.println("c:" + Integer.toBinaryString(c));
System.out.println("0xF:" + Integer.toBinaryString(0xF));
印刷品

b:11111111111111111111111111111111
a:1111
c:11111111111111111111111111111111
0xF:1111
所以
b&OxF

11111111111111111111111111111111
00000000000000000000000000001111  (AND)
--------------------------------
                            1111   (15)
b|0

11111111111111111111111111111111
00000000000000000000000000000000   (OR)
--------------------------------
11111111111111111111111111111111   (-1)

这里的问题是,按位运算符处理整数或长整数,而不是字节
b&0xF
基本上被视为
((int)b)和((int)0xF)
。您可以从每个操作的JLS定义中进行跟踪

  • 第一个(定义了
    &
    |
    )解释了当两个操作数都可转换为整数基元类型时,“首先对操作数执行二进制数字升级(§5.6.2)。”
  • 反过来说,除非任一操作数是
    浮点
    双精度
    长型
    ,否则这两个值都将加宽到
    int
  • 最后,在中定义了加宽,并指出“将有符号整数值的加宽转换为整数类型T simply sign扩展整数值的两个补表示以填充更宽的格式。”字节是有符号的()
因此,您的
b
字节在被右操作数AND'd或or'ed之前,使用符号扩展名被加宽为
int

注意,这意味着
b&0F
的结果应该是
int
,而不是
字节。事实上就是这样(这意味着显式将其强制转换为
int
是多余的)。您可以通过将其自动装箱到
对象
,然后检查该对象的类型来测试:

byte b = -1;
Object o = (b & 0xF); 
System.out.println(o.getClass());
// prints "class java.lang.Integer", not "class java.lang.Byte"

0
进行OR运算会得到另一个数字。这就是你要问的吗?不。我的意思是我认为0 |((字节)-1)应该是15,但实际上它是-1。用一个值对零进行排序会返回不变的值。Java的
byte
是有符号的,所以当转换到
int
@stevp时,你总是会得到符号扩展。它链接到HotLicks的评论。