Несовместимая ошибка "возможного преобразования с потерями из 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, и значение константного выражения представимо в типе переменной.