有人可以向我解释下面的Java代码在做什么吗?

时间:2010-11-08 02:01:21

标签: java binary hex bit-manipulation

byte s[] = getByteArray()
for(.....)
Integer.toHexString((0x000000ff & s[i]) | 0xffffff00).substring(6);

我知道您正在尝试将字节转换为十六进制字符串。我不明白的是如何做到这一点。例如,如果s [i]是00000001(十进制1),那么请解释一下:

  1. 为什么是0x000000ff& 00000001?为什么不直接使用00000001?
  2. 为什么来自#1 | 0xffffff00?
  3. 最后为什么要应用substring(6)?
  4. 感谢。

1 个答案:

答案 0 :(得分:11)

这基本上是因为字节是用Java签名的。如果将字节提升为int,则它将签名扩展,这意味着字节0xf2将变为0xfffffff2。符号扩展是一种通过将最高有效(符号)位复制到所有高阶位来在加宽时保持值相同的方法。上述两个值都是-14的二进制补码表示法。如果您将0xf2扩展为0x000000f2,则可能是242,可能不是您想要的内容。

因此&操作是剥离任何扩展位,只留下最低有效8位。但是,由于你无论如何都要在下一步将这些位强制为1,这一步似乎有点浪费。

此后的|操作会强制所有高位为1,这样您就可以保证从ffffff00ffffffff包含8个字符的字符串(从{到{ {1}}不会向您提供前导零,它会将toHexString转换为7而不是您想要的"7"

然后应用"07",以便您只获得这八个十六进制数字中的最后两个。

当您可以使用substring(6)时,确保您获得双字符十六进制字符串似乎是一种非常复杂的方法。但是,当String.format ("%02x", s[i])被引入时,这个特定的代码片段可能早于Java 5。


如果您运行以下程序:

String.format

你会看到两个表达式是相同的 - 它只是吐出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"); } } ,因为这两个表达式在所有情况下都会产生相同的结果。

相关问题