2015-12-20 4 views
2

У меня этот код:странное поведение байта в Java

public class First 
{ 
    public static void main(String[] args) 
    { 
     byte b=50; 
     byte c=b*2; //Error  
     byte d=50*2; //d=100 
     byte e=(byte)258; //e=258%256; 
     byte f=(byte)128; //f=128%256; 
    } 
} 
  1. Я знаю, что любое арифметическое выражение, включающее byte сначала повышен до int, а затем она выполняется. Поэтому я ожидал d=50*2, чтобы сообщить об ошибке, потому что результат 50*2 является значением int , и мы храним его в byte без какого-либо явного приведения типов. Если Java делает кастинг неявно, почему c=b*2 сообщает об ошибке ?
  2. Я знаю, что если я хочу, чтобы сохранить значение, которое не находится в пределах диапазона в byte переменной, то я должен явно ввести приведение его в byte и значение, которое будет сохранено это значение по модулю 256 (Размер байта). Поэтому почему byte f=(byte)128 return -128? С 128 % 256 = 128, так что я ожидаю f=128, но он возвращает -128. Зачем?

Большое спасибо.

+1

50 * 2 является постоянной во время компиляции. 128 находится вне диапазона байтов. –

ответ

2

Это связано с тем, что 50*2; будет разрешен во время компиляции, а b*2; будет разрешен во время выполнения. Итак, во время компиляции Java компилятор уверен, что результатом 50*2; будет 100. Но в случае b*2;, как вы уже упомянули, результатом арифметической операции является int, а компилятор не может быть уверен, что результат может превышать byte лимитов, поэтому он жалуется и хочет, чтобы вы убедились в вещах путем каста или изменения типа.

Вы можете использовать javap -v Test.class, чтобы проверить то же. Смотрите ниже:

public static void main(java.lang.String[]); 
    flags: ACC_PUBLIC, ACC_STATIC 
    Code: 
    stack=2, locals=2, args_size=1 
     0: bipush  100 
     2: istore_1 
     3: getstatic  #2     // Field java/lang/System.out:Ljava/io/PrintStream; 
     6: iload_1 
     7: invokevirtual #3     // Method java/io/PrintStream.println:(I)V 
     10: return 
    LineNumberTable: 
     line 4: 0 
     line 5: 3 
     line 6: 10 

Для вашего второго вопроса, то @Eran уже объяснил, используя представление битов 128 и 258, и вы можете прочитать дальше от JLS §5.1.3. Narrowing Primitive Conversion

сужающее преобразование знакового целого к интегральный тип T просто отбрасывает все, кроме n бит младшего разряда, где n - это число бит, используемое для представления типа T. В дополнение к возможной потере информации о величине числового значения это может вызвать знак результирующего значения от знака входа значение.

1

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

Поэтому int128, двоичное представление 0......010000000 становится байт 10000000 (вы возьмете младшие 8 бит), который -128.

С другой стороны, 258 - 0........01000000010, а когда вы берете низкие 8 бит, вы получаете 00000010, что составляет 2.

1

Автомат Тип Сниженные в Java

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

Чтобы понять, почему, учтите следующее. В выражении точность , необходимая для промежуточного значения, иногда превышает диапазон любого из операндов.

Например, рассмотрим следующее выражение:

byte a = 40; 
byte b = 50; 
byte c = 100; 
int d = a * b/c; 

В результате промежуточного срока a * b легко превышает диапазон любого из его байтовых операндов. Чтобы справиться с такой проблемой, Java автоматически рекламирует каждый byte, short или char операнд до int при оценке выражения.

Это означает, что подвыражение a*b выполняется с использованием целых чисел, а не байтов. Таким образом, 2000, результат промежуточного выражения 50 * 40, является законным, даже если a и b оба указаны как байты типа.

Полезно, как автоматические рекламные акции, они могут вызвать непонятные ошибки компиляции .

Например, это, казалось бы, правильный код вызывает проблему:

byte b = 50; 
b = b * 2; // Error! Cannot assign an int to a byte! 

Код пытающийся для хранения 50 * 2, вполне допустимого byte значения, обратно в byte переменные. Однако, поскольку операнды автоматически повышались до int, когда выражение оценивалось, результат также повышался до int. Таким образом, результат выражения теперь имеет тип int, который не может быть присвоен byte без использования cast.

Это верно, даже если, как и в этом конкретном случае, назначенное значение по-прежнему будет соответствовать целевому типу. В тех случаях, когда вы понимаете последствия переполнения, вы должны использовать явное приведение, такие, как

byte b = 50; 
b = (byte)(b * 2); 

, которая дает правильное значение 100.

Смежные вопросы