简体   繁体   中英

Type mismatch: cannot convert from int to byte using ternary operator

Working on a project utilizing byte array manipulation, I have attempted to write something like this:

boolean enabled = getEnabled();

byte enabledByte = enabled ? 0x01 : 0x00; // compile error

The issue that I am facing, is that the above will not compile.

Type mismatch: cannot convert from int to byte

However if I expand this to the following, it works without issue:

boolean enabled = getEnabled();

byte enabledByte;
if (enabled) {

    enabledByte = 0x01;
} else {

    enabledByte = 0x00;
}

Leading me to the question

Why can I not use byte assignments in short if statements?

Number literals are naturally of type int , not byte .

The language has a special implicit conversion from numeric literals (< 128) to byte , so your second example doesn't need a cast.

However, wrapping the literals in a conditional operator creates an expression of type int that isn't a literal, so you need the cast.

0x00 and 0x01 are int literals: they are expressions with int type. An int can't usually be assigned to a byte , but it can if the expression is compile-time constant, provided the value is in the range of byte .

With the conditional, the assigned value is compile-time constant:

if (enabled) {
  enabledByte = 0x01;
} else {
  enabledByte = 0x00;
}

These assignments are completely separate from the compiler's point of view. There is one statement which assigns the constant value 1, and one statement which assigns the constant value 0.

For each statement, the compiler can guarantee that fits into the range of byte, so it automatically narrows the assigned value to byte.

However, the assignment with the conditional operator:

enabledByte = enabled ? 0x01 : 0x00;

The rhs expression is of type int , but isn't compile time constant, because enabled isn't known at compile time. It doesn't matter that the two possible values are compile-time constant, and both would fit into a byte : the non-constant first operand makes it non-constant. As such, the result of the conditional operator expression cannot be automatically narrowed.

The most efficient solution to this is to cast the second and third operands to byte :

enabled ? (byte) 0x01 : (byte) 0x00

This is better than

(byte) (enabled ? 0x01 : 0x00)

Because the latter will cast at runtime, each time the expression is evaluated, whereas the former does not: the operands are already bytes at compile-time, so no cast is necessary.

You need at least one cast to flip the ternary expression to a byte , it's defaulting to an int because of the ternary.

byte enabledByte = enabled ? (byte) 0x01 : 0x00; 

It works the same way if you use decimal literals

byte enabledByte = enabled ? (byte) 1 : 0; 

See also JLS-15.25.2 - Numeric Conditional Expressions which says (in part)

Otherwise, binary numeric promotion ( §5.6.2 ) is applied to the operand types, and the type of the conditional expression is the promoted type of the second and third operands.

The rule governing the narrowing conversion from int to byte is specified in the language specification, section on assignment contexts (emphasis on constant expression):

In addition, if the expression is a constant expression (§15.28) of type byte , short , char , or int :

  • A narrowing primitive conversion may be used if the type of the variable is byte , short , or char , and the value of the constant expression is representable in the type of the variable.

...

If the type of the expression cannot be converted to the type of the variable by a conversion permitted in an assignment context, then a compile-time error occurs.

The ternary conditional expression enabled ? 0x01 : 0x00 enabled ? 0x01 : 0x00 is not a constant expression , unlike the integer literals. Therefore, it cannot be implicitly converted using narrowing conversion.

Note that you can solve the error by casting one of the operands of the conditional expression:

byte enabledByte = enabled ? (byte) 0x01 : 0x00;

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