Java - &0xff 给出从 8 到 31 的位为 1

Java - &0xff gives bits from 8 to 31 as 1's

我在使用 0xff 执行 AND 运算符时遇到问题。

public Pixel(int x, int y, int p) {
    this.x = x;
    this.y = y;
    pixelValue = p;
    A = (byte) ((p>>24) & 0xff);
    R = (byte) ((p>>16) & 0xff);
    R = (byte) (R&0xff);
    G = (byte) ((p>>8) & 0xff);
    B =(byte) (p & 0xff);
    printAll();
}
void printAll() {
    System.out.println("A "+Integer.toBinaryString(A));
    System.out.println(Byte.toUnsignedInt(A));
    System.out.println("R "+Integer.toBinaryString(R));
    System.out.println(Byte.toUnsignedInt(R));
    System.out.println("G "+Integer.toBinaryString(G));
    System.out.println(Byte.toUnsignedInt(G));
    System.out.println("B "+Integer.toBinaryString(B));
    System.out.println(Byte.toUnsignedInt(B));
    System.out.println("pixelValue"+pixelValue);
    System.out.println(Integer.toBinaryString((byte)(pixelValue)));
}

做的时候Pixel p = new Pixel(0,0,2145687240); 我得到

A 1111111
127
R 11111111111111111111111111100100
228
G 11111111111111111111111110010110
150
B 11111111111111111111111111001000
200
pixelValue-56
11111111111111111111111111001000

问题来了,为什么R、G、B全是1?为什么 A 只有 7 位? 为什么在调用 &0xff 时我得到 111111111111111111111111100100?这不应该取消除前 8 个字节以外的所有内容吗?

字节从 0255(含),因为它们可以容纳 2^8=256 个值。至少这是未签名的定义。

这里要问自己的问题是:如何表示负数?典型的方法是使用称为二进制补码的东西。第一位不是像通常那样在关闭时表示 0,在打开时表示 2^(n-1),而是在关闭时表示 0,在打开时表示 -2^(n-1)

因此,228 在内部存储为 11100100。如果你从基数 2 转换它,你会看到它等于 228... 但只有在无符号时才如此。

有符号时,后7位代表100。然后,第一个位,不代表128,而是代表-128。因此,签名时的值为-28

然后,将其转换为整数时,由于整数有32位,因此第一个位将表示-2147483648,因此后31位需要表示28 + 2147483648,这是 1111111111111111111111111100100 的来源。因此,-28 的 32 位表示是 11111111111111111111111111100100.

如果您实际上想要 228,您可能希望对 Byte.toUnsignedInt 的结果调用 Integer.toBinaryString,顾名思义,它会将其转换为无符号 数。这里的问题是它被签名,这意味着它是-28,而不是你想要的228