У меня проблема с приведенными ниже инструкциями Java:
byte b = 10;
byte r = (byte) (b * b); // Giving correct result
byte r = (byte) b * b; // Giving error " POSSIBLE LOSS OF PRECISION"
Почему обязательно ставить скобки в b * b?
У меня проблема с приведенными ниже инструкциями Java:
byte b = 10;
byte r = (byte) (b * b); // Giving correct result
byte r = (byte) b * b; // Giving error " POSSIBLE LOSS OF PRECISION"
Почему обязательно ставить скобки в b * b?
(byte) b * b преобразует значение первого b в byte (которое является избыточным, поскольку оно уже было byte) и умножает его на значение второго b. Умножение двух byte переводит их в int первым, так как для byte s нет оператора *. Следовательно, результатом является int, и его нельзя присвоить byte переменной.
С другой стороны, (byte)(b * b) приводит результат умножения int к byte, который может быть присвоен byte переменной.
Это описано в JLS в 5.6.2. Двоичное числовое продвижение:
Когда оператор применяет двоичное числовое продвижение к паре операндов, каждый из которых должен обозначать значение, которое может быть преобразовано в числовой тип, применяются следующие правила по порядку:
Если какой-либо операнд имеет ссылочный тип, он подвергается распаковке преобразования (§5.1.8).
Расширяющее примитивное преобразование (§5.1.2) применяется для преобразования одного или обоих операндов, как указано в следующих правилах:
Если один из операндов имеет тип double, другой преобразуется в double.
В противном случае, если один из операндов имеет тип float, другой преобразуется в float.
В противном случае, если один из операндов имеет тип long, другой преобразуется в long.
В противном случае оба операнда преобразуются в тип int.
Проблема литья
byte r = (byte) (b * b);
Приводит (byte) тип к результату (b * b)
byte r = (byte) b * b;
Он преобразует (byte) тип только в первый b, поэтому он станет ((byte) b) * b
По правилу приоритета вы приводите только первый b к байту вместо всего результата.
И Java следуют некоторым правилам, как вы можете видеть здесь
Все целочисленные значения (byte, short и int) в арифметических операциях (
+,−,*,/,%) преобразуются в типintперед выполнением арифметической операции. Однако, если одно из значений в арифметической операции (+,−,*,/,%) являетсяlong, то все значения преобразуются вlongтип перед выполнением арифметической операции.
Итак, просто бросая первый b вы делаете это:
byte = byte * integer
Следовательно:
byte = integer
Таким образом, возникла ошибка.
Переменные byte типа должны быть [-128, 127], поэтому компилятор не должен принимать никаких операций, b*b;b+b;bb;b/b без приведения к результату операции, например: (byte)(b*b).
В приведенном ниже коде при изменении типа результата на int он компилируется.
byte b=10;
byte c=(byte)b*b; //incompatible but correct when c is int
byte d=((byte)b)*b; //incompatible but correct when d is int
byte r=(byte)(b*b);
byte t= b*b; //incompatible but correct when t is int
byte e=(byte)b/b; //incompatible but correct when e is int
byte f=((byte)b)/b; //incompatible but correct when f is int
byte o=(byte)(b/b);
byte w=b/b; //incompatible but correct when w is int
byte g=(byte)b+b; //incompatible but correct when g is int
byte p=((byte)b)+b; //incompatible but correct when p is int
byte q=(byte)(b+b);
byte x=b+b; //incompatible but correct when x is int
byte h=(byte)b-b; //incompatible but correct when h is int
byte v=((byte)b)-b; //incompatible but correct when v is int
byte s=(byte)(b-b);
byte y=b-b; //incompatible but correct when y is int
byte k=(byte)b;
byte u=b;
НОТА
Как отметил @andy Truner в комментариях, когда b является final, все предыдущие инструкции компилируются !!, за исключением следующих настроек:
final byte fn=-120;
byte z=fn-b; //this does not compile even when both final, because the result would be -130, out of the byte type interval!!