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

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

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

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

Ответы [ 2 ]

28 голосов
/ 16 мая 2019

JLS 15,25. объясняет это поведение.

Фрагмент # 1:

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

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

Фрагмент # 2:

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

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

Snippet #3:

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

Второй и третий операнды byte, поэтому тип выражения byte, который можно присвоить переменной byte.

Фрагмент # 4:

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

8 голосов
/ 16 мая 2019

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


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

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

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


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

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

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

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


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

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

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

...