使用0xff进行定位,需要澄清

在以下代码段中,请考虑使用注释等效替换第8行

1. private static String ipToText(byte[] ip) { 2. StringBuffer result = new StringBuffer(); 3. 4. for (int i = 0; i  0) 6. result.append("."); 7. 8. result.append(ip[i]); // compare with result.append(0xff & ip[i]); 9. } 10. 11. return result.toString(); 12. } 

.equals()测试确认添加0xff不会改变任何东西。 是否有理由应用此蒙版?

Java中的byte是介于-128和127之间的数字(有符号,就像Java中的每个整数一样(如果要计算它,则为char除外))。 通过和0xff一起使用,你强迫它成为0到255之间的正int

它的工作原理是因为Java将使用符号扩展执行向int的扩展转换,因此您将使用负int来代替负byte 。 使用0xff屏蔽将仅保留低8位,从而使数字再次为正(以及您最初的意图)。

您可能没有注意到差异,因为您使用仅包含小于128的值的byte[]进行了测试。

小例子:

 public class A { public static void main(String[] args) { int[] ip = new int[] {192, 168, 101, 23}; byte[] ipb = new byte[4]; for (int i =0; i < 4; i++) { ipb[i] = (byte)ip[i]; } for (int i =0; i < 4; i++) { System.out.println("Byte: " + ipb[i] + ", And: " + (0xff & ipb[i])); } } } 

这打印

 Byte: -64, And: 192 Byte: -88, And: 168 Byte: 101, And: 101 Byte: 23, And: 23 

显示byte ,当它仍然是int时进入字节的内容&操作的结果之间的差异。

由于您已在此处使用字节数组,并且您正在执行按位操作,因此可以忽略Java如何将所有字节视为已签名。 毕竟,你现在正在处理位级别,并且在位级别上没有“有符号”或“无符号”值。

使用全1来掩盖8位值(一个字节)只是浪费周期,因为什么都不会被屏蔽掉。 如果被比较的两个位都为真,则咬合AND将返回一个真,因此如果掩码包含全1,则保证在AND操作之后掩码值的所有位将保持不变。

请考虑以下示例:

 掩盖上半字节:
     0110 1010
 AND 0000 1111(0x0F)
   = 0000 1010 
 掩盖下半字节:
     0110 1010
 AND 1111 0000(0xF0)
   = 0110 0000 
 掩盖......呃,没什么:
     0110 1010
 AND 1111 1111(0xFF)
   = 0110 1010

当然,如果你在这里使用一个完整的int,你会得到其他人的结果说:你“强制”int等同于无符号字节。

在这个例子中,我看不出它会有什么不同。 你是用一个字节和0xff。 根据定义,字节具有8位,并且添加屏蔽最后8位。 所以你要花8的最后8,这不会做任何事情。

如果你正在使用它的东西大于一个字节,一个短或一个int或其他东西,那么使用0xff进行定义是有意义的。

如果存在负字节,这应该只会有所不同。 & 0xff通常用于将字节解释为无符号。