Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

“Type mismatch: cannot convert int to byte”

I saw people asking questions about the error "Type mismatch: cannot convert int to byte". But they are mostly caused by arithmetic operations involved.

Here is my case:
(This happens when I want to play with bits in 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.

The thing is that if it is 8 bits and the highest digit is 1, then compiler gives error. I want to know why. The prefix 0b means it is a binary literal so why the compiler take the highest digit as a signed int digit or something like that?

Thanks for answering.

[Edit3:]

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

[Edit2: bitwise & operation somehow triggers the error as well]

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: screenshot updated] enter image description here

enter image description here

like image 389
Weishi Z Avatar asked Nov 17 '13 03:11

Weishi Z


3 Answers

You got a point, suspecting this is about signed integers. In Java, ALL integers types (byte, short, int, long) are ALWAYS signed. Java used two's complement to store signed (read "all") values. That basically means, that if the first bit of any type (not first bit specified in the literal, but first bit stored) is 1, the number is negative. If it's 0, it's positive.

Second thing of importance is: There are no BYTE literals in Java. There are int literals, and long literals. Every nubmer written down (be it in binary (0b prefix), octal (0 prefix), decimal (no prefix) or hex (0x prefix)) is an integer literal, unless you append an L (either lowercase or uppercase), it's long. There is no way to write down any short or byte directly.

Now, that means, that all those examples you wrote down, are creating an int first. You don't create bytes there.

So, the last part is, what happens if you try to store that int inside a byte - without casting or with casting. If you are casting explicitely you basically tell Java to just ignore any bits that don't fit. They will be cut - even if this changes the value of the number (for examples, see below). If you don't cast, bits will still be cut. But Java won't do that, if it changes the value - to make sure you really mean what you're doing.

To link this all to the exmamples from the question:
int 0b01111111 is 127
byte 0b01111111 is 127
-> conversion possible without any overflow, so Java will do it even without an explicit cast

int 0b10000000 is 128
byte 0b10000000 is -128
-> An overflow occrus when converting, so Java will throw an error if there is no explicit cast.

like image 156
Johannes H. Avatar answered Sep 22 '22 21:09

Johannes H.


I think bytes in java are signed, which would make 0b10000000 out of range. 127 would be the largest byte possible, the reason being the two's compliment representation of negative numbers.

like image 30
richard Avatar answered Sep 23 '22 21:09

richard


Byte variables CAN hold the value 0b1000000, but since they are signed, that represents the integer value -128. The reason it can't convert the literal is that when you write it as a literal with no cast, the compiler sees it as (int) 0b10000000 which is the integer value POSITIVE 128.

Any integer value above 127 is out of bounds for a byte, since bytes are signed and can only hold integer values from -128 to 127. That's where the overflow comes in (to hold 128, you'd need a ninth bit for the sign). Any time a signed value has 1 as its most significant bit, it represents a negative number, so in order to put a number like 0b10000000 into a byte, you would need to represent a negative value in your literal. For example, the value -128 would be equivalent to the int 0b11111111111111111111111110000000, so you would need to use that as your literal, or else, much simpler, just explicitly cast it as a byte, like: (byte) 0b10000000

like image 23
user3489270 Avatar answered Sep 23 '22 21:09

user3489270