Inconsistent "possible lossy conversion from int to byte" compile-time error
Asked Answered
E

2

30

Examine the following code snippets:

Snippet #1

int a=20;
int b=30;
byte c= (a>b)? 20:30;
Error:
incompatible types: possible lossy conversion from int to byte
byte c= (a>b)? 20:30;

Snippet #2

int a=20;
int b=30;
byte h1=70;
byte c= (a>b)? 20:h1;

Snippet #3

int a=20;
int b=30;
byte h1=70;
byte h2=89;
byte c= (a>b)? h1:h2;

Snippet #4

byte c= (true)? 20:30;

All of these compile fine except for Snippet #1. How is this behavior justified? If Snippet #1 produces the "possible lossy conversion" error, Snippets #2 and 4 should also, given that they still contain literals of type int. Why do they compile successfully?

Egis answered 16/5, 2019 at 7:22 Comment(3)
If you change int to final int (constant) the compiler will see that the values of a and b are in the byte range -128..127. For int variables the compiler does no such evaluation and assumes the int could overflow the byte range.Egret
@JoopEggen But why should range of a and b matters or even their data types; (a>b) is a condition and will evaluate to either true or false and based on that either 20 or 30 will be assigned to variable c. I am not getting why the range and type of variables a and b should matter. What must matter is the range and data type of literals 20 and 30 or variable h1 and h2 which we are using to assign to variable c. But it seems from code-4 that data type and range of variables a and b matters.Egis
There general is a warning/error when assigning a larger typed variable to a smaller one, for unintended loss of information. But there come answers better clarifying the state with java I hopeEgret
H
30

J.L.S 15.25. explains this behavior.

Snippet #1:

If the second and third operands have the same type (which may be the null type), then that is the type of the conditional expression

Both the second and third operands are int literals, so the type of the expression is also int, which cannot be assigned to a byte variable without explicit cast. Hence the compilation error.

Snippet #2:

If one of the operands is of type T where T is byte, short, or char, and the other operand is a constant expression (§15.28) of type int whose value is representable in type T, then the type of the conditional expression is T.

One operand is a byte and the other is an int literal whose value can be represented as byte, so the type of the expression is byte, which can be assigned to a byte variable.

Snippet #3:

If the second and third operands have the same type (which may be the null type), then that is the type of the conditional expression

Both the second and third operands are byte, so the type of the expression is byte, which can be assigned to a byte variable.

Snippet #4:

Since all 3 operands are constant, the entire ternary expression is a constant expression, so the compiler treats this expression as a simple assignment - byte c = 20; - which is valid.

Hartmunn answered 16/5, 2019 at 7:47 Comment(0)
G
7

This behaviour is described in the language spec.


Case 1 and 3 are described by the same point:

If the second and third operands have the same type, then that is the type of the conditional expression.

In case 1, the operands are of type int, so the overall expression is of type int, so it is incompatible. In case 3, the operands of of type byte, hence the result is compatible.


Case 2 is surprising to me: I would have expected that to fail as well, because the int operand would cause the conditional expression to be of int type.

However, this behaviour is described in the following point:

If one of the operands is of type T where Tis byte, short, or char, and the other operand is a constant expression (§15.28) of type int whose value is representable in type T, then the type of the conditional expression is T.

The 20 is a constant expression which fits in byte, hence the result is a byte.


Case 4 is also described by the "operands of the same type rule" used for cases 1 and 3; however, the fact that the condition is now constant makes it a constant expressions.

A constant expressions of int type is implicitly narrowed when assigning to a variable of narrower type, as described in Assignment contexts:

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

Gimble answered 16/5, 2019 at 7:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.