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

Почему байт не принимает 0xff в java?

Почему java-компилятор не позволяет мне помещать 0xff в byte, 0xff длиной 8 бит, которая равна размеру byte datatype.

Может кто-нибудь объяснить, почему 1 работает и почему 2 не делает?

class a
{
        public static void main(String[] args)
        {
                // 1 :: results in error
                byte a = 0xff;          
                System.out.printf("%x\n",a);

                //2 :: works fine
                byte a = (int)0xff              
                System.out.printf("%x\n",a);
        }
}

EDIT Я прочитал ответ, утверждая, что 0xff 255, как это сделать? Разве это не 1111 1111, что делает 0xff, -128 или 255 или что-то в этом роде. Почему это будет не просто рассматривать его как 1111 1111, а не 8 бит этого байта в 1.

4b9b3361

Ответ 1

Тип Java byte - это 8-битный целочисленный тип со знаком со значениями в диапазоне от -128 до +127. Литерал 0xff представляет +255, который находится вне этого диапазона.

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

Во втором примере приведение (byte) выполняет явное сужающее преобразование, которое удаляет старшие биты целочисленного литерала... давая вам значение -127 в вашей переменной byte.


На самом деле, ситуация с первым примером немного сложнее. Учтите это:

byte a = 1;         // OK
int i = 1;
byte b = i;         // Compilation error
byte c = (byte) i;  // OK

В обычных обстоятельствах вы не можете назначить int на byte без приведения. Однако если присваиваемое значение является литералом, а литеральное значение находится в диапазоне целевого типа, язык Java разрешает присваивание без приведения. Литеральное значение неявно сужается от int до byte.

Это описано в JLS §5.2, в котором определяются преобразования, которые могут быть выполнены в назначении:

"Преобразование примитивного сужения может использоваться, если тип переменной - байтовый, короткий или символьный, а значение константного выражения представимо в типе переменной".

И, как вы можете видеть, это относится не только к литералам. Это относится ко всем (во время компиляции) константным выражениям!


ПОСЛЕДУЮЩИЕ UP

Я прочитал ответ, утверждая, что 0xff это 255, как же так? Разве это не 1111 1111, что делает 0xff, -128 или 255 или что-то в этом роде?

Литерал 0xff является целочисленным литералом типа int. Значение int литерала 0xff на самом деле является 0000 0000 0000 0000 0000 0000 1111 1111 в двоичном или +255 в десятичном виде. Напротив, целочисленное значение -128 имеет битовую комбинацию 1111 1111 1111 1111 1111 1111 1000 0000.

Почему он не будет трактовать его как 1111 1111, а не как 8 битов этого байта в 1?

Потому что 0xff является целочисленным литералом с типом int. Это не 8-битный литерал, потому что 8-битные литералы не существуют в Java. JLS §3.10.1 гласит:

"Целочисленный литерал имеет тип long, если к нему добавляется суффикс ASCII-буквы L или l (ell); в противном случае он относится к типу int (§4.2.1). "

Ответ 2

0xff представляет собой шестнадцатеричное представление числа. Другими словами, это число 16.

f = 15 в шестнадцатеричном формате.

Значение равно

15 * 16^1 + 15 * 16^0 = 255

Это целочисленный литерал (использует 4 байта), который превышает диапазон значений byte.

Ни один из двух приведенных вами примеров не будет компилироваться, так как ни один из них не соответствует диапазону значений byte -128 to 127. Вы можете прочитать о диапазонах значений примитивного типа здесь.

Это будет работать

byte a = (byte)0xff; 
System.out.println(a);

и напечатайте -1, потому что преобразование байта 255 сокращается байтом -1.

Ответ 3

0xff - 255. Хотя это соответствует 8-разрядному целому числу без знака, byte подписывается (от -128 до 127). Сужение приведет к удалению высоких бит и соответствует 8 в 8 без учета знака.

Ответ 4

Во-первых, если я пытаюсь запустить ваш код, то и 2-й случай тоже не работает. Вы бросаете 0xff в примитивный тип данных int (который имеет 32 бит) и хотите сохранить его в байте с 8 бит. Java рассматривает ваш первый случай как int тоже, что приводит к той же проблеме.

Поскольку тип байта java представляет собой 8-разрядное целое значение со знаком (от -128 до 127), для вывода/печати байта как шестнадцатеричного, вы можете использовать Integer.toHexString( "примитивный байт" и 0xFF) где 'и 0xFF' - это битмаска, чтобы учесть, что Integer использует 32-битный int, а байт использует 8 бит.

    byte myByte = (byte)0xff;
    System.out.println(Integer.toHexString(myByte & 0xFF));

Выводится:

ff