“Type mismatch: cannot convert int to byte”

12,786

Solution 1

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.

Solution 2

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.

Solution 3

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

Share:
12,786
Weishi Z
Author by

Weishi Z

Updated on June 14, 2022

Comments

  • Weishi Z
    Weishi Z about 2 years

    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

  • Johannes H.
    Johannes H. over 10 years
    @jprofitt: Oh. Snap, you're right there. That... might change the answer... Gotta do some reading on that.
  • Johannes H.
    Johannes H. over 10 years
    Actually, I'm even more confused now. According to the language spec, there are no byte literals. So neither of those cases should work...
  • Weishi Z
    Weishi Z over 10 years
    Thanks for helping! I was counting the digits as well 2 minutes ago... I should put the length in comments to improve readability.
  • Lion
    Lion over 10 years
    @JohannesH. : Binary literals are introduced in Java 7. So in lower versions, they won't be available.
  • Johannes H.
    Johannes H. over 10 years
    Thanks for the hint! That means I'll have to look into the Java 7 spec.
  • Johannes H.
    Johannes H. over 10 years
    @Lion: Ah. No. You read that wrong. It's not the binary literals that confused me, its the BYTE literals. All literals should always be int, long can be specified by adding a l prefix. Short and byte have to be casted. Always.
  • Lion
    Lion over 10 years
    @JohannesH. : I don't know the exact terminology but I have just put this statement byte b = 0b10000000; in NetBeans IDE with jdk 6, it gave this compilation error - binary literals are not supported in -source 1.6 (use -source 7 or higher to enable binary literals)
  • Johannes H.
    Johannes H. over 10 years
    What confuses me, is that ANY integer literal should always create an int. No byte. So assigning a literal to a byte type without casting, should always end in failure,
  • Weishi Z
    Weishi Z over 10 years
    In two's compliment representation, 0b10000000 is -128, which is still in the range of an int in java.
  • richard
    richard over 10 years
    Right, but you were trying to make a byte, hence the error. The type byte cannot hold the value 0b10000000
  • Johannes H.
    Johannes H. over 10 years
    Got that. @richard seems to be right. This isn't about how you can specify bytes, this is about how you can NOT specify them and about how conversion from int to byte works. See my edited answer.
  • Johannes H.
    Johannes H. over 10 years
    +1 for leading the way here, I agree, this has to be the answer. Added a little more details to this, see my answer.
  • Dennis Meng
    Dennis Meng over 10 years
    @JohannesH. Shouldn't that be "append L", not "prepend L"?
  • Johannes H.
    Johannes H. over 10 years
    @DennisMeng it should ;)
  • richard
    richard over 10 years
    Yes, its the lack of a binary literal that causes the issue. +1
  • Weishi Z
    Weishi Z over 10 years
    I still didn't get it why a byte cannot hold the value of 0b10000000? It is 8 bits. It should represent some value, right? Why overflow?
  • Weishi Z
    Weishi Z over 10 years
    @JohannesH. In two's complement representation, let's say for 8 bits only, 0b10000000 is -128, which is still in the range of a 8-bit two's complement number. So I didn't get it why there is an overflow. And could you please edit the answer to include what happens when you do explicit converting in the last line? (what is the converted byte)
  • Weishi Z
    Weishi Z over 10 years
    @Lion That is because binary literals with prefix "0b" is only supported after java 7. So you need to download java 7 and choose the JRE to 1.7.
  • Johannes H.
    Johannes H. over 10 years
    @WeishiZeng See my answer. It's because if the value is stored in a byte, the first bit is the 1, therefore it's a negative value. If stored in an int, the frist bit is a zero (not specified in your literal), and therefore a positive number. If you safe the integer into a byte, the sign will therefore switch -> this is what you call an overflow.
  • Weishi Z
    Weishi Z over 10 years
    Got your point. "There are no BYTE literals in Java. There are int literals, and long literals." This makes me fully understand the whole thing.
  • Johannes H.
    Johannes H. over 10 years
    Great! Nice to hear you got it, after all, glad I could help. Still good question, took me a while to figure it out myself ^^