javacompiler-errorslanguage-specifications

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


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?


Solution

  • 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.