这基本上是因为字节是用 Java 签名的。如果你将一个字节提升为一个 int,它将符号扩展,这意味着字节 0xf2 将变为 0xfffffff2。符号扩展是一种在扩展时保持值相同的方法,方法是将最高有效(符号)位复制到所有高阶位中。以上两个值都是-14,采用二进制补码表示法。相反,如果您将0xf2 扩大到0x000000f2,那么它将是242,可能不是你想要的。
所以& 操作是去除这些扩展位中的任何一个,只留下最低有效的 8 位。但是,由于无论如何您都将在下一步中将这些位强制为 1,因此这一步似乎有点浪费。
随后的 | 操作将强制所有这些高位为 1,这样您就可以保证从 ffffff00 到 ffffffff (包括 toHexString 不给出前导零,它会将7 转换为"7",而不是您想要的"07"。
然后应用substring(6),这样您就只能得到这八个十六进制数字中的最后两个。
当您可以使用String.format ("%02x", s[i]) 时,确保您得到一个两个字符的十六进制字符串似乎是一种非常复杂的方法。但是,当引入 String.format 时,这种特殊的 sn-p 代码可能早于 Java 5。
如果你运行以下程序:
public class testprog {
public static void compare (String s1, String s2) {
if (!s1.equals(s2))
System.out.println ("Different: " + s1 + " " + s2);
}
public static void main(String args[]) {
byte b = -128;
while (b < 127) {
compare (
Integer.toHexString((0x000000ff & b) | 0xffffff00).substring(6),
String.format("%02x", b, args));
b++;
}
compare (
Integer.toHexString((0x000000ff & b) | 0xffffff00).substring(6),
String.format("%02x", b, args));
System.out.println ("Done");
}
}
您会看到这两个表达式是相同的 - 它只是吐出Done,因为这两个表达式在所有情况下都会产生相同的结果。