简体   繁体   中英

Java: why do I receive the error message "Type mismatch: cannot convert int to byte"

If you declare variables of type byte or short and attempt to perform arithmetic operations on these, you receive the error "Type mismatch: cannot convert int to short" (or correspondingly "Type mismatch: cannot convert int to byte").

byte a = 23;
byte b = 34;
byte c = a + b;

In this example, the compile error is on the third line.

Although the arithmetic operators are defined to operate on any numeric type, according the Java language specification (5.6.2 Binary Numeric Promotion), operands of type byte and short are automatically promoted to int before being handed to the operators.

To perform arithmetic operations on variables of type byte or short, you must enclose the expression in parentheses (inside of which operations will be carried out as type int), and then cast the result back to the desired type.

byte a = 23;
byte b = 34;
byte c = (byte) (a + b);

Here's a follow-on question to the real Java gurus: why? The types byte and short are perfectly fine numeric types. Why does Java not allow direct arithmetic operations on these types? (The answer is not "loss of precision", as there is no apparent reason to convert to int in the first place.)

Update: jrudolph suggests that this behavior is based on the operations available in the JVM, specifically, that only full- and double-word operators are implemented. Hence, to operator on bytes and shorts, they must be converted to int.

The answer to your follow-up question is here:

operands of type byte and short are automatically promoted to int before being handed to the operators

So, in your example, a and b are both converted to an int before being handed to the + operator. The result of adding two int s together is also an int . Trying to then assign that int to a byte value causes the error because there is a potential loss of precision. By explicitly casting the result you are telling the compiler "I know what I am doing".

I think, the matter is, that the JVM supports only two types of stack values: word sized and double word sized.

Then they probably decided that they would need only one operation that works on word sized integers on the stack. So there's only iadd, imul and so on at bytecode level (and no operators for bytes and shorts).

So you get an int value as the result of these operations which Java can't safely convert back to the smaller byte and short data types. So they force you to cast to narrow the value back down to byte/short.

But in the end you are right: This behaviour is not consistent to the behaviour of ints, for example. You can without problem add two ints and get no error if the result overflows.

The Java language always promotes arguments of arithmetic operators to int, long, float or double. So take the expression:

a + b

where a and b are of type byte. This is shorthand for:

(int)a + (int)b

This expression is of type int. It clearly makes sense to give an error when assigning an int value to a byte variable.

Why would the language be defined in this way? Suppose a was 60 and b was 70, then a+b is -126 - integer overflow. As part of a more complicated expression that was expected to result in an int, this may become a difficult bug. Restrict use of byte and short to array storage, constants for file formats/network protocols and puzzlers.

There is an interesting recording from JavaPolis 2007. James Gosling is giving an example about how complicated unsigned arithmetic is (and why it isn't in Java). Josh Bloch points out that his example gives the wrong example under normal signed arithmetic too. For understandable arithmetic, we need arbitrary precision.

In Java Language Specification (5.6.2 Binary Numeric Promotion):

1 If any expression is of type double, then the promoted type is double, and other expressions that are not of type double undergo widening primitive conversion to double.

2 Otherwise, if any expression is of type float, then the promoted type is float, and other expressions that are not of type float undergo widening primitive conversion to float.

3 Otherwise, if any expression is of type long, then the promoted type is long, and other expressions that are not of type long undergo widening primitive conversion to long.

4 Otherwise, none of the expressions are of type double, float, or long. In this case, the promoted type is int, and any expressions that are not of type int undergo widening primitive conversion to int.

Your code belongs to case 4. variables a and b are both converted to an int before being handed to the + operator. The result of + operation is also of type int not byte

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM