为什么我不能在Java中屏蔽长数据类型上的32位

为什么我不能在Java中屏蔽长数据类型上的32位,java,binary,bit-manipulation,masking,Java,Binary,Bit Manipulation,Masking,我不明白为什么会这样。我试图在一个长的内存中屏蔽java的最低有效32位,但它不能正确地屏蔽第33位和第34位,甚至更远。这是我的例子 class Main { public static void main(String[] args) { long someVal = 17592096894893l; //hex 0xFFFFAAFAFAD long mask = 0xFF; //binary long result = mask & someVal;

我不明白为什么会这样。我试图在一个长的内存中屏蔽java的最低有效32位,但它不能正确地屏蔽第33位和第34位,甚至更远。这是我的例子

class Main {
  public static void main(String[] args) {
    long someVal = 17592096894893l; //hex  0xFFFFAAFAFAD
    long mask = 0xFF; //binary
    long result = mask & someVal;                  

    System.out.println("Example 1 this works on one byte");
    System.out.printf("\n%x %s", someVal, Long.toBinaryString(someVal) );
    System.out.printf("\n%x %s", result, Long.toBinaryString(result) );

    long someVal2 = 17592096894893l; //hex  0xFFFFAAFAFAD
    mask = 0xFFFFFFFF; //binary
    result = mask & someVal2; 
    System.out.println("\nExample 2 - this does not work");
    System.out.printf("\n%x %s", someVal2, Long.toBinaryString(someVal2) );
    System.out.printf("\n%x %s", result, Long.toBinaryString(result) );
  }
}
我希望结果将最高有效字节降为零,因为AND操作在32位上执行。这是我得到的输出

Example 1 - this works
ffffaafafad 11111111111111111010101011111010111110101101
ad 10101101
Example 2 - this does not work

ffffaafafad 11111111111111111010101011111010111110101101
ffffaafafad 11111111111111111010101011111010111110101101

我希望能够屏蔽long值的前4个最低有效字节。

我相信您在这里看到的是,Java使用符号扩展将整数转换为long

首先,这段代码应该做什么

int myInt = -1;
long myLong = myInt;
System.out.println(myLong);
这应该直观地打印出-1,这确实是发生的事情。我的意思是,如果在将int转换为long时,我们没有得到与开始时相同的数字,那就有点奇怪了

现在,让我们看一下下面的代码:

int myInt = 0xFFFFFFFF;
long myLong = myInt;
System.out.println(myLong);
这印的是什么?0xFFFFFF是有符号32位数字-1的十六进制版本。这意味着此代码与上述代码完全等效,因此它应该(并且确实)打印相同的值,-1

但是编码为long的值-1没有表示0x00000000FFFFFFFF。那将是232-1,而不是-1。相反,由于它是64位长,-1表示为0xFFFFFFFFFFFFFFFFF。哎呀,所有的高位都被激活了!这使得它作为位掩码不是很有效

Java中的规则是,如果将int转换为long,如果int的第一位是1,那么long的所有32个高位也将被设置为1。这样,将整数转换为long将保留数值

如果要制作实际长度为64位的位掩码,请使用长文字而不是int文字对其进行初始化:

mask = 0xFFFFFFFFL; // note the L
为什么这会有不同?没有L,Java将代码视为

  • 创建整数值0xFFFFFF=-1,给出32个1位
  • 将该整数值转换为长整数。为此,使用符号扩展将其转换为长值-1,一行64位
  • 但是,如果包含L,Java会解释如下内容:

  • 创建长值0xFFFFFF=232-1,即32个零位后跟32个一位
  • 将该值指定给掩码

  • 希望这有帮助

    非常感谢你。这很有道理。我没有意识到十六进制正在初始化为32位十六进制。只需将
    result
    的类型更改为
    int
    并使用强制转换即可。