Продвижение типа в Java

У меня проблема с приведенными ниже инструкциями 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?

Ответ 1

(byte) b * b преобразует значение первого b в byte (которое является избыточным, поскольку оно уже было byte) и умножает его на значение второго b. Умножение двух byte переводит их в int первым, так как для byte s нет оператора *. Следовательно, результатом является int, и его нельзя присвоить byte переменной.

С другой стороны, (byte)(b * b) приводит результат умножения int к byte, который может быть присвоен byte переменной.

Это описано в JLS в 5.6.2. Двоичное числовое продвижение:

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

  1. Если какой-либо операнд имеет ссылочный тип, он подвергается распаковке преобразования (§5.1.8).

  2. Расширяющее примитивное преобразование (§5.1.2) применяется для преобразования одного или обоих операндов, как указано в следующих правилах:

    • Если один из операндов имеет тип double, другой преобразуется в double.

    • В противном случае, если один из операндов имеет тип float, другой преобразуется в float.

    • В противном случае, если один из операндов имеет тип long, другой преобразуется в long.

    • В противном случае оба операнда преобразуются в тип int.

Ответ 2

Проблема литья

byte r = (byte) (b * b);

Приводит (byte) тип к результату (b * b)

byte r = (byte) b * b;

Он преобразует (byte) тип только в первый b, поэтому он станет ((byte) b) * b

Ответ 3

По правилу приоритета вы приводите только первый b к байту вместо всего результата.

И Java следуют некоторым правилам, как вы можете видеть здесь

Все целочисленные значения (byte, short и int) в арифметических операциях (+, , *, /, %) преобразуются в тип int перед выполнением арифметической операции. Однако, если одно из значений в арифметической операции (+, , *, /, %) является long, то все значения преобразуются в long тип перед выполнением арифметической операции.

Итак, просто бросая первый b вы делаете это:

byte = byte * integer

Следовательно:

byte = integer

Таким образом, возникла ошибка.

Ответ 4

Переменные 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!!