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

dat*_*ser 4 java binary hex bit-manipulation

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

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

  1. 为什么是0x000000ff&00000001?为什么不直接使用00000001?
  2. 为什么会产生#1 | 0xffffff00?
  3. 最后为什么要应用substring(6)?

谢谢.

pax*_*blo 11

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

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

|操作之后的,这将迫使所有的高位为1,这样你保证,从获得的8个字符的字符串ffffff00,通过ffffffff包容性的(因为toHexString不给你前导零,这将转化7"7",而不是"07"你想要的) .

substring(6)随后进行涂布,使得您只能获得最后两个的这八个十六进制数字.

当你可以使用时,这似乎是一种非常复杂的方法,可以确保你得到一个双字符的十六进制字符串String.format ("%02x", s[i]).但是,这个特定的代码片段可能在String.format引入时可能早于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");
    }
}
Run Code Online (Sandbox Code Playgroud)

你会看到两个表达式是相同的 - 它只是吐出来,Done因为这两个表达式在所有情况下产生相同的结果.