Может кто-нибудь объяснить мне, что делает следующий Java-код? - PullRequest
4 голосов
/ 08 ноября 2010
byte s[] = getByteArray()
for(.....)
Integer.toHexString((0x000000ff & s[i]) | 0xffffff00).substring(6);

Я понимаю, что вы пытаетесь преобразовать байт в шестнадцатеричную строку.Чего я не понимаю, так это как это сделать.Например, если s [i] было 00000001 (десятичное 1), чем вы могли бы объяснить:

  1. Почему 0x000000ff & 00000001?Почему бы напрямую не использовать 00000001?
  2. Почему результат # 1 |0xffffff00?
  3. Наконец, почему применяется подстрока (6)?

Спасибо.

1 Ответ

11 голосов
/ 08 ноября 2010

Это в основном потому, что байты подписаны в 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]). Однако возможно, что этот конкретный фрагмент кода может предшествовать 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");
    }
}

вы увидите, что два выражения идентичны - оно просто выплевывает Done, поскольку оба выражения дают одинаковый результат во всех случаях.

...