Java:почему я получаю сообщение об ошибке “Несоответствие типов:не удается преобразовать значение int в байт”

StackOverflow https://stackoverflow.com/questions/81392

Вопрос

Если вы объявляете переменные типа byte или short и пытаетесь выполнить с ними арифметические операции, вы получаете сообщение об ошибке "Несоответствие типа:не удается преобразовать int в short" (или, соответственно, "Несоответствие типов:не удается преобразовать int в байт").

byte a = 23;
byte b = 34;
byte c = a + b;

В этом примере ошибка компиляции находится в третьей строке.

Это было полезно?

Решение

Хотя арифметические операторы определены для работы с любым числовым типом, согласно спецификации языка Java (5.6.2 Двоичное числовое продвижение), операнды типа byte и short автоматически преобразуются в int перед передачей операторам.

Чтобы выполнить арифметические операции над переменными типа byte или short, необходимо заключить выражение в круглые скобки (внутри которых операции будут выполняться как тип int), а затем привести результат обратно к желаемому типу.

byte a = 23;
byte b = 34;
byte c = (byte) (a + b);

Вот следующий вопрос к настоящим Java-гуру:почему?Типы byte и short являются совершенно правильными числовыми типами.Почему Java не допускает прямых арифметических операций над этими типами?(Ответ заключается не в "потере точности", поскольку, во-первых, нет видимых причин для преобразования в int .)

Обновить:юдольф предполагает, что такое поведение основано на операциях, доступных в JVM, в частности, на том, что реализованы только операторы с полным и двойным словом.Следовательно, для работы с байтами и короткими записями они должны быть преобразованы в int.

Другие советы

Ответ на ваш последующий вопрос находится здесь:

операнды типа byte и short автоматически преобразуются в int перед передачей операторам

Итак, в вашем примере, a и b оба преобразуются в int перед передачей оператору +.Результат сложения двух ints вместе - это тоже int.Пытаясь затем присвоить это int к a byte значение вызывает ошибку, поскольку существует потенциальная потеря точности.Явно приводя результат, вы сообщаете компилятору: "Я знаю, что я делаю".

Я думаю, дело в том, что JVM поддерживает только два типа значений стека:размер слова и двойной размер слова.

Затем они, вероятно, решили, что им понадобится только одна операция, которая работает с целыми числами размером со слово в стеке.Таким образом, на уровне байт-кода есть только iadd, imul и так далее (и никаких операторов для байтов и коротких замыканий).

Таким образом, в результате этих операций вы получаете значение int, которое Java не может безопасно преобразовать обратно в меньшие байтовые и короткие типы данных.Таким образом, они заставляют вас выполнять приведение, чтобы сузить значение обратно до байта / короткого.

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

Язык Java всегда переводит аргументы арифметических операторов в значения int, long, float или double .Итак , возьмем выражение:

a + b

где a и b имеют тип byte.Это сокращение для:

(int)a + (int)b

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

Почему язык должен быть определен таким образом?Предположим, что a равно 60, а b равно 70, тогда a+b равно -126 - целочисленное переполнение.Как часть более сложного выражения, которое, как ожидалось, приведет к int , это может стать сложной ошибкой.Ограничьте использование байтового и короткого хранилища в массив, констант для форматов файлов / сетевых протоколов и головоломок.

Есть интересная запись из JavaPolis 2007.Джеймс Гослинг приводит пример того, насколько сложна арифметика без знака (и почему ее нет в Java).Джош Блох указывает, что его пример также дает неверный пример при обычной знаковой арифметике.Для понятной арифметики нам нужна произвольная точность.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top