"Несоответствие типов: невозможно преобразовать int к Byte"



Я видел, как люди задавали вопросы об ошибке "Type mismatch: cannot convert int to byte". Но в основном они вызваны арифметическими операциями.



Вот мой случай:

(Это происходит, когда я хочу поиграть с битами в Eclipse Kepler)



//java 7 binary literals

byte a = 0b01111111; //8-bit it compiles

byte b = 0b10000000; //8-bit error: Type mismatch: cannot convert int to byte.

byte c = (byte) 0b10000000; //8-bit it works fine if casted.


Дело в том, что если он равен 8 битам, а самая высокая цифра равна 1, то компилятор выдает ошибку.
Я хочу знать, почему. Префикс 0b означает, что это двоичный литерал, так почему компилятор принимает самую высокую цифру как знаковую int-цифру или что-то вроде этого?



Спасибо, что ответили.



[Edit3:]



byte a = -128; //a = 0xFF = 11111111 (8 bits), compiler says ok.
byte b = 0b11111111; //compiler error


[Edit2: побитовое & операция каким-то образом вызывает ошибку, а также]



byte a = 0b00000000;  //8 bits
a = (a&0xFF); //gives same error: Type mismatch: cannot convert int to byte
a = (byte)(a&0xFF); //it is fine to cast


[Edit1: скриншот обновлен]
Введите описание изображения здесь



Введите описание изображения здесь

485   3  

3 ответов:

Вы попали в точку, подозревая, что речь идет о знаковых целых числах. В Java все типы целых чисел(byte, short, int, long) всегда подписываются. В Java используются два дополнения для хранения подписали (читай "все") значений. Это в основном означает, что если первый бит любого типа (не первый бит, указанный в литерале, но Первый БИТ, сохраненный) равен 1, то число отрицательно. Если он равен 0, то он положительный.

Вторая важная вещь: в Java нет байтовых литералов. Существуют int литералы и long константы. Каждый записанный nubmer (будь то двоичный (0b префикс), восьмеричный (0 префикс), десятичный (без префикса) или шестнадцатеричный (0x префикс)) является целочисленным литералом, если вы не добавляете L (либо в Нижнем, либо в верхнем регистре), это long. Нет никакого способа записать любые short или byte напрямую. Теперь это означает, что все те примеры, которые вы записали, создают int в первую очередь. Вы не создаете bytes там. Итак, последняя часть заключается в том, что произойдет, если вы попытаетесь сохранить это int внутри byte - без отливки или с отливкой. Если вы бросаете явно, вы в основном говорите Java просто игнорировать любые биты, которые не подходят. Они будут сокращены - даже если это изменит значение числа (примеры см. ниже). Если вы не бросите, кусочки все равно будут разрезаны. Но Java этого не сделает, если изменит значение - чтобы убедиться, что вы действительно имеете в виду то, что делаете.

Чтобы связать все это с примерами из вопроса:
int 0b01111111 есть 127
byte 0b01111111 is 127
-> преобразование возможно без переполнения, поэтому Java сделает это даже без явного приведения

int 0b10000000 есть 128
byte 0b10000000 ИС -128
- >Переполнение происходит при преобразовании, поэтому Java выдаст ошибку, если нет явного приведения.

Я думаю, что байты в java подписаны, что сделало бы 0b10000000 вне диапазона. 127 будет самым большим возможным байтом, причина в том, что два комплимента представляют отрицательные числа.

Байтовые переменные могут содержать значение 0b1000000, но так как они подписаны, это представляет собой целое значение -128. Причина, по которой он не может преобразовать литерал, заключается в том, что когда вы пишете его как литерал без приведения, компилятор видит его как (int) 0b10000000, что является целочисленным значением, положительным 128.

Любое целочисленное значение выше 127 выходит за пределы байта, так как байты имеют знак и могут содержать только целочисленные значения от -128 до 127. Вот где происходит переполнение (чтобы удержать 128, вам понадобится девятый бит для знака). Каждый раз, когда знаковое значение имеет 1 в качестве своего наиболее значимого бита, оно представляет отрицательное число, поэтому для того, чтобы поместить число, подобное 0b10000000 в байт, вам нужно будет представить отрицательное значение в вашем литерале. Например, значение -128 будет эквивалентно int 0b111111111111111111111110000000, поэтому вам нужно будет использовать его в качестве литерала, или же, гораздо проще, просто явно привести его в виде байта, например: (byte) 0b10000000

Comments

    Ничего не найдено.