Преобразование байта в int в Java

Я создал безопасное случайное число и поместил его значение в байт. Вот мой код.

SecureRandom ranGen = new SecureRandom();
byte[] rno = new byte[4]; 
ranGen.nextBytes(rno);
int i = rno[0].intValue();

Но я получаю сообщение об ошибке:

 byte cannot be dereferenced

person Ashwin    schedule 06.03.2012    source источник
comment
Есть разница между байтом и байтом. Последний представляет собой объект, который поддерживает метод .intValue(). Первый - это необработанное значение байта, и просто присвойте его как int i = rno[0];   -  person wuppi    schedule 06.03.2012
comment
См. Также stackoverflow.com/questions/2383265/convert-4 -bytes-to-int   -  person DNA    schedule 06.03.2012


Ответы (6)


Ваш массив состоит из byte примитивов, но вы пытаетесь вызвать для них метод.

Вам не нужно делать ничего явного, чтобы преобразовать byte в int, просто:

int i=rno[0];

... поскольку это не уныние.

Обратите внимание, что поведение преобразования byte в int по умолчанию заключается в сохранении знака значения (помните, что byte - это тип со знаком в Java). Так например:

byte b1 = -100;
int i1 = b1;
System.out.println(i1); // -100

Если вы думали о byte как о неподписанном (156), а не подписанном (-100), в Java 8 есть _ 10_:

byte b2 = -100; // Or `= (byte)156;`
int = Byte.toUnsignedInt(b2);
System.out.println(i2); // 156

До Java 8, чтобы получить эквивалентное значение в int, вам нужно было замаскировать биты знака:

byte b2 = -100; // Or `= (byte)156;`
int i2 = (b2 & 0xFF);
System.out.println(i2); // 156

Просто для полноты №1: если вы действительно по какой-то причине хотите использовать различные методы Byte (здесь вам не нужно), вы можете использовать преобразование бокса:

Byte b = rno[0]; // Boxing conversion converts `byte` to `Byte`
int i = b.intValue();

Или Byte конструктор :

Byte b = new Byte(rno[0]);
int i = b.intValue();

Но опять же, здесь это вам не нужно.


Просто для полноты № 2: если это было понижающим (например, если вы пытались преобразовать int в byte), все, что вам нужно, это приведение:

int i;
byte b;

i = 5;
b = (byte)i;

Это гарантирует компилятору, что вы знаете, что это отрицательный результат, поэтому вы не получите ошибку «Возможная потеря точности».

person T.J. Crowder    schedule 06.03.2012
comment
Использование конструктора Byte - не лучшая идея. Просто сделай Byte b = rno[0]; вместо этого. - person xehpuk; 11.02.2014
comment
@xehpuk: Я должен был упомянуть конверсии бокса, сделайте это сейчас. - person T.J. Crowder; 11.02.2014
comment
Почему в этом случае преобразование бокса превосходит конструктор байтов? насколько я понимаю, преобразование бокса в конечном итоге в конечном итоге использует конструктор Byte? мое понимание неверно? - person user1; 30.11.2017
comment
Последний раз я проверял в Java 8 Byte class предоставляет статический метод toUnsignedInt (byte). Это должно упростить преобразование и сделать код более читаемым. - person yolob 21; 25.04.2020
comment
@ yolob21 - Спасибо. Да, ответ появился на два года раньше Java 8. :-) - person T.J. Crowder; 25.04.2020

byte b = (byte)0xC8;
int v1 = b;       // v1 is -56 (0xFFFFFFC8)
int v2 = b & 0xFF // v2 is 200 (0x000000C8)

В большинстве случаев v2 - это то, что вам действительно нужно.

person Sheng.W    schedule 08.09.2015
comment
это потому, что 32-битная машина сгенерировала длинный 0xffffffc8, спасибо. - person herbertD; 17.12.2017
comment
Это правильный ответ, и v2 почти всегда то, что вам нужно. Неявное преобразование байта в int без & 0xff является источником ошибок в Java. - person Luke Hutchison; 06.12.2018
comment
На самом деле это не из-за ошибок в неявном преобразовании Java. Это из-за недопонимания разработчика. Байт-примитив Java поддерживает только значения от -128 до 127. Если кто-то попытается вставить в него беззнаковое значение (например, 0xC8), он может перевернуться с кучей ведущих (из-за обозначения дополнения до двух). Точно так же в этом вопросе для полного битового пространства может быть установлен знаковый бит, и числовое продвижение будет делать то же самое. - person ingyhere; 08.12.2018
comment
Java фактически выполняет числовое преобразование под капотом, согласно JLS, что означает, что оба операнда в любом случае преобразуются в примитивы типа int. - person ingyhere; 08.12.2018
comment
Не ошибки в Java, а ошибки в пользовательском коде, написанном на Java :) Большинство программистов не понимают, что байты подписаны в Java, и, честно говоря, это глупое поведение по умолчанию, когда они рассматривают байты как подписанные в спецификации Java, но они сделали это для согласованность с другими целочисленными типами, поскольку ни у одного из них нет беззнаковых версий. Та же проблема возникает при преобразовании шорт в целые, поскольку люди обычно не понимают, что шорты подписаны. (Однако с помощью байтов легче вызывать ошибки расширения подписи из-за очень ограниченного диапазона значений.) Однако люди действительно ожидают, что будут подписаны целые и длинные числа. - person Luke Hutchison; 09.12.2018

если вы хотите объединить 4 байта в один int, вам нужно сделать

int i= (rno[0]<<24)&0xff000000|
       (rno[1]<<16)&0x00ff0000|
       (rno[2]<< 8)&0x0000ff00|
       (rno[3]<< 0)&0x000000ff;

Я использую 3 специальных оператора | - это побитовое логическое ИЛИ, & - это логическое И, а << - это левый сдвиг

по сути, я объединяю 4 8-битных байта в один 32-битный int, сдвигая байты на место и объединяя их вместе

Я также гарантирую, что продвижение знаков не повлияет на результат с & 0xff

person ratchet freak    schedule 06.03.2012
comment
Я бы сделал (rno [0] & 0x000000ff) ‹---------------- 24 | (rno [1] & 0x000000ff) ... и т. д., чтобы затем я мог сделать этот операнд AND константой. В качестве альтернативы, вы также можете просто сделать ((int) rno [0]) ‹---------------- 24 | ((int) rno [1]) ‹---------------- 16 | ... поскольку приведение типа автоматически помещает байтовые значения в примитивное внутреннее пространство. - person ingyhere; 08.04.2014
comment
@ingyhere Ваш альтернативный вариант неверен! См. Ответ Sheng.W. Вам почти всегда необходимо выполнить (b & 0xff) для преобразования байта в int, а не ((int) b) или эквивалентное неявное приведение из-за расширения знака. - person Luke Hutchison; 06.12.2018
comment
Вы получили меня @LukeHutchison ... Второй в моем комментарии работает только для значений без знака (положительное пространство) в диапазоне примитива байтов Java (до 127). - person ingyhere; 08.12.2018
comment
Положительный диапазон знакового значения не является беззнаковым значением, у него все еще есть знак «+» :) Байты, короткие, целые и длинные числа подписаны в Java, беззнаковой версии нет! - person Luke Hutchison; 09.12.2018

Примитивные типы данных (например, байтовые) не имеют методов в java, но вы можете делать это напрямую:

int i=rno[0];
person MByD    schedule 06.03.2012
comment
Нет, это Byte.intValue, а Byte - класс, byte - примитивный тип данных. - person MByD; 06.03.2012
comment
Это неполный ответ. См. Ответ Sheng.W. Вам почти всегда нужно делать (b & 0xff), чтобы преобразовать byte в int, а не ((int) b) или эквивалентное неявное приведение, int i = b;, из-за расширения знака для байтов с высоким битом. Забывание сделать это - частый источник ошибок. - person Luke Hutchison; 09.12.2018

Байты прозрачно конвертируются в целые числа.

Просто скажи

int i= rno[0];
person Saintali    schedule 06.03.2012
comment
Но обратите внимание, что знак сохраняется, что не всегда то, что вам нужно (в Java нет беззнаковых байтов). - person DNA; 06.03.2012

Думал будет:

byte b = (byte)255;
int i = b &255;
person joe    schedule 10.05.2016