Несовместимая ошибка "возможного преобразования с потерями из int в байты" во время компиляции

Изучите следующие фрагменты кода:

Фрагмент №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;

Фрагмент № 2

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

Фрагмент № 3

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

Фрагмент № 4

byte c= (true)? 20:30;

Все они прекрасно компилируются, за исключением Snippet # 1. Насколько это поведение оправдано? Если Snippet # 1 выдает ошибку "возможного преобразования с потерями", Snippets # 2 и 4 также должны это делать, учитывая, что они все еще содержат литералы типа int. Почему они успешно компилируются?

Ответ 1

JLS 15.25. объясняет это поведение

Фрагмент №1:

Если второй и третий операнды имеют одинаковый тип (который может быть нулевым типом), то это тип условного выражения

И второй, и третий операнды являются литералами типа int, поэтому типом выражения также является int, которое нельзя назначить byte переменной без явного преобразования. Отсюда и ошибка компиляции.

Фрагмент № 2:

Если один из операндов имеет тип T, где T является байтом, коротким или char, а другой операнд является константным выражением (§15.28) типа int, значение которого представимо в типе T, тогда тип условного выражения Т.

Один операнд является byte а другой - литералом int, значение которого может быть представлено в виде byte, поэтому тип выражения - byte, который может быть назначен byte переменной.

Фрагмент № 3:

Если второй и третий операнды имеют одинаковый тип (который может быть нулевым типом), то это тип условного выражения

И второй, и третий операнды являются byte, поэтому тип выражения - byte, который может быть назначен byte переменной.

Фрагмент № 4:

Поскольку все 3 операнда являются константами, все троичное выражение является константным выражением, поэтому компилятор обрабатывает это выражение как простое присваивание - byte c = 20; - который действителен.

Ответ 2

Это поведение описано в спецификации языка.


Случаи 1 и 3 описываются одной и той же точкой:

Если второй и третий операнды имеют одинаковый тип, то это тип условного выражения.

В случае 1 операнды имеют тип int, поэтому общее выражение имеет тип int, поэтому оно несовместимо. В случае 3 операнды типа byte, следовательно, результат является совместимым.


Случай 2 меня удивляет: я ожидал, что и это тоже не получится, потому что операнд int вызовет условное выражение типа int.

Тем не менее, это поведение описано в следующем пункте:

Если один из операндов имеет тип T, где Tis byte, short или char, а другой операнд является константным выражением (§15.28) типа int, значение которого представимо в типе T, тогда тип условного выражения равен T,

20 является константным выражением, которое помещается в байтах, следовательно, результатом является байт.


Случай 4 также описывается "операндами одного и того же правила типа", используемыми для случаев 1 и 3; однако тот факт, что условие теперь является постоянным, делает его постоянным выражением.

Константные выражения типа int неявно сужаются при присваивании переменной более узкого типа, как описано в контекстах присваивания:

Сужающее примитивное преобразование может использоваться, если переменная имеет тип byte, short или char, и значение константного выражения представимо в типе переменной.