"Несоответствие типов: невозможно преобразовать 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: скриншот обновлен]
3 ответов:
Вы попали в точку, подозревая, что речь идет о знаковых целых числах. В Java все типы целых чисел(
Вторая важная вещь: в Java нет байтовых литералов. Существуютbyte
,short
,int
,long
) всегда подписываются. В Java используются два дополнения для хранения подписали (читай "все") значений. Это в основном означает, что если первый бит любого типа (не первый бит, указанный в литерале, но Первый БИТ, сохраненный) равен 1, то число отрицательно. Если он равен 0, то он положительный.int
литералы иlong
константы. Каждый записанный nubmer (будь то двоичный (0b префикс), восьмеричный (0 префикс), десятичный (без префикса) или шестнадцатеричный (0x префикс)) является целочисленным литералом, если вы не добавляетеL
(либо в Нижнем, либо в верхнем регистре), этоlong
. Нет никакого способа записать любыеshort
илиbyte
напрямую. Теперь это означает, что все те примеры, которые вы записали, создаютint
в первую очередь. Вы не создаетеbyte
s там. Итак, последняя часть заключается в том, что произойдет, если вы попытаетесь сохранить этоint
внутриbyte
- без отливки или с отливкой. Если вы бросаете явно, вы в основном говорите Java просто игнорировать любые биты, которые не подходят. Они будут сокращены - даже если это изменит значение числа (примеры см. ниже). Если вы не бросите, кусочки все равно будут разрезаны. Но Java этого не сделает, если изменит значение - чтобы убедиться, что вы действительно имеете в виду то, что делаете.Чтобы связать все это с примерами из вопроса:
int 0b01111111
есть 127byte 0b01111111
is 127
-> преобразование возможно без переполнения, поэтому Java сделает это даже без явного приведения
int 0b10000000
есть 128byte 0b10000000
ИС -128
- >Переполнение происходит при преобразовании, поэтому Java выдаст ошибку, если нет явного приведения.
Я думаю, что байты в java подписаны, что сделало бы 0b10000000 вне диапазона. 127 будет самым большим возможным байтом, причина в том, что два комплимента представляют отрицательные числа.
Байтовые переменные могут содержать значение 0b1000000, но так как они подписаны, это представляет собой целое значение -128. Причина, по которой он не может преобразовать литерал, заключается в том, что когда вы пишете его как литерал без приведения, компилятор видит его как (int) 0b10000000, что является целочисленным значением, положительным 128.
Любое целочисленное значение выше 127 выходит за пределы байта, так как байты имеют знак и могут содержать только целочисленные значения от -128 до 127. Вот где происходит переполнение (чтобы удержать 128, вам понадобится девятый бит для знака). Каждый раз, когда знаковое значение имеет 1 в качестве своего наиболее значимого бита, оно представляет отрицательное число, поэтому для того, чтобы поместить число, подобное 0b10000000 в байт, вам нужно будет представить отрицательное значение в вашем литерале. Например, значение -128 будет эквивалентно int 0b111111111111111111111110000000, поэтому вам нужно будет использовать его в качестве литерала, или же, гораздо проще, просто явно привести его в виде байта, например: (byte) 0b10000000
Comments