Подтвердить что ты не робот

Самый элегантный способ преобразования байта в int в Java

Пример кода:

int a = 255;
byte b = (byte) a;
int c = b & 0xff; // Here be dragons
System.out.println(a);
System.out.println(b);
System.out.println(c);

Итак, мы начинаем с целочисленного значения 255, преобразуем его в байт (становимся -1), а затем преобразуем его обратно в int с помощью магической формулы. Ожидаемый результат:

255
-1
255

Мне интересно, является ли этот a & 0xff самым элегантным способом для этого преобразования. checkstyle, например, жалуется на использование магического номера в этом месте, и не рекомендуется игнорировать это значение для этой проверки, потому что в других местах 255 действительно может быть волшебным числом, которого следует избегать. И это довольно раздражает, чтобы определить константу для таких вещей самостоятельно. Поэтому я задаюсь вопросом, есть ли стандартный метод в JRE, который делает это преобразование? Или, возможно, уже определенная константа с наивысшим значением без знака байта (аналогично Byte.MAX_VALUE, которое является наивысшим подписанным значением)

Итак, чтобы задать короткий вопрос: как я могу преобразовать байт в int без использования магического номера?

Хорошо, до сих пор упоминались следующие возможности:

  • Продолжайте использовать & 0xff и игнорируйте магический номер 255 в checkstyle. Недостаток: другие места, которые могут использовать это число в какой-либо другой области (не бит-операции), также не проверяются. Преимущество: Короткое и легко читаемое.
  • Определите для меня свою константу, а затем используйте код, например & SomeConsts.MAX_UNSIGNED_BYTE_VALUE. Недостаток: если мне это нужно в разных классах, тогда я должен определить свой собственный постоянный класс только для этой константы. Преимущество: здесь нет магических чисел.
  • Сделайте какую-нибудь умную математику, как b & ((1 << Byte.SIZE) - 1). Вывод компилятора, скорее всего, тот же, поскольку он оптимизируется до постоянного значения. Недостаток: Довольно много кода, трудночитаемого. Преимущество: Пока 1 не определяется как магическое число (checkstyle игнорирует его по умолчанию), здесь нет магического числа, и нам не нужно определять пользовательские константы. И когда байты переопределены до 16 бит в один прекрасный день (просто шучу), то он все еще работает, потому что тогда Byte.SIZE будет 16, а не 8.

Есть ли еще идеи? Может быть, какая-то другая умная побитовая операция, которая короче, чем выше, и использует только числа, такие как 0 и 1?

4b9b3361

Ответ 1

Этот стандартный способ сделать это преобразование. Если вы хотите избавиться от жалоб на проверку, попробуйте определить константу, это может помочь:

 public final static int MASK = 0xff;

BTW - имейте в виду, что он по-прежнему является обычным преобразованием. byte является подписанным типом данных, поэтому byte никогда не может удерживать значение 255. Байт может хранить битовый шаблон 1111 1111, но это представляет целочисленное значение -1.

Таким образом, на самом деле вы выполняете бит-операции - и бит-операции всегда требуют некоторых магических чисел.


BTW-2: Да, существует константа Byte.MAX_VALUE, но это - потому что byte подписан - определяется как 2 7 -1 (= 127). Так что это не поможет в вашем случае. Вам нужна константа байта для -1.

Ответ 2

Игнорировать контрольный стиль. 0xFF не является магическим числом. Если вы определяете константу для нее, константа является магической константой, которая намного менее понятна, чем сама 0xFF. Каждый программист, получивший образование в последние столетия, должен быть более знаком с 0xFF, чем со своей девушкой, если таковой имеется.

следует ли писать такой код?

for(int i = Math.ZERO; ... )

Ответ 4

Я написал метод для этого типа

public static int unsigned(byte x) {
    return int (x & 0xFF);
}

который также перегружен для коротких и int-параметров (где int увеличивается до длинного).

Вместо 0xFF вы можете использовать Byte.MAX_VALUE + Byte.MAX_VALUE + 1, чтобы сохранить FindBug закрытым, но я считаю его обфускацией. И это слишком легко сделать неправильно (с предыдущими версиями).

Ответ 5

Java 8 предоставляет Byte.toUnsignedInt и Byte.toUnsignedLong (возможно, для действительно больших байтов):

byte b = (byte)255;
int c = Byte.toUnsignedInt(b); // 255
long asLong = Byte.toUnsignedLong(b); // 255