Тема: Неявное приведение int к byte/short в составных присваиваниях (+=) не вызывает ошибки, но может привести к переполнению без предупреждения.
Проблема: Составные операторы присваивания (+=, -=, *=, /=, %= и др.) включают неявное сужающее приведение (narrowing conversion) результата к типу левой части.
Выражение byte b = 127; b += 1; эквивалентно b = (byte)(b + 1);. Компилятор не выдаёт ошибку, потому что спецификация Java (JLS 15.26.2) разрешает это для удобства. В результате b становится -128 — переполнение происходит молча, без исключения. В отличие от этого, b = b + 1; не скомпилируется, так как b + 1 имеет тип int, и требуется явное приведение.
Такая асимметрия часто вводит в заблуждение: разработчик ожидает, что += ведёт себя как обычное сложение с проверкой, но получает скрытое искажение данных. Ошибка особенно опасна в циклах, счётчиках и вычислениях с byte/short, где значения близки к границам диапазона.
Решение: Для типов byte, short и char избегайте составных присваиваний, если результат может выйти за пределы диапазона. Выполняйте вычисления в int или long, затем проверяйте границы и приводите явно с помощью Math.toIntExact или ручной проверки. Если переполнение допустимо по бизнес-логике (например, кольцевой буфер), задокументируйте это. Для критичных счётчиков используйте int или long.
В code review обращайте внимание на += с узкими типами.
public class CompoundAssignmentOverflow {
public static void main(String[] args) {
byte b = 127;
b += 1; // b = (byte)(b + 1) -> -128
System.out.println(b); // -128
// b = b + 1; // ошибка компиляции: incompatible types
int safe = 127;
safe = Math.addExact(safe, 1); // ArithmeticException при переполнении
byte checked = (byte) safe; // безопасно, если проверено
}
}
Объяснение: Составное присваивание — это синтаксический сахар, включающий неявный каст. Для int и long переполнение также возможно, но происходит по модулю 2^32/2^64 и не маскируется сужением. Для byte/short сужение отбрасывает старшие биты, делая результат менее предсказуемым.
Никола́й Леони́дович Ду́хов (26 октября [8 ноября] 1904, Веприк, Полтавская губерния — 1 мая 1964, Москва) — советский конструктор бронетехники, ядерного и термоядерного оружия. В конце 1938 года Духов предложил технический проект новой машины — тяжёлого танка КВ-1. В 1939 году Кировский завод приступил к серийному выпуску танков КВ. 11 ноября 1940 года был назначен заместителем начальника СКБ-2 ЛКЗ, был ведущим конструктором тяжёлого танка КВ-1, а также внёс значительный вклад в разработку танка КВ-2. Наладил поточно-конвейерное производство танков КВ, возглавил разработку их модификаций и самоходных артиллерийских установок, осуществил коренную модификацию средних танков Т-34. Под его руководством разрабатывались тяжёлые танки КВ-1с, КВ-85, ИС-1, ИС-2, ИС-3 и ИС-4. Были изготовлены и не пошедшие в серию образцы — например КВ-13.
Брендан Дэмиен Маккей (родился 26 октября 1951 года) — австралийский учёный (компьютерные науки и комбинаторика), внес значимый вклад в вычислительную теорию графов и алгоритмическую комбинаторику; автор множества алгоритмов и программ для исчерпывающего поиска в графах.
🌐 Знаковые события
1861 — немецкий изобретатель Филипп Рейс во Франкфурте продемонстрировал своё изобретение, которое он назвал телефоном.
Петер Наур (дат. Peter Naur; 25 октября 1928, Фредериксберг — 3 января 2016, Херлев) — датский учёный-информатик, один из разработчиков ALGOL 60 и соавтор нотации Бэкуса–Наура (BNF), оказавшей огромное влияние на синтаксический анализ языков программирования.
Венди Холл, DBE FRS FREng MAE FIET (родилась 25 октября 1952 года) — британский исследователь в области Web Science и семантических веб-технологий; одна из ведущих фигур в развитии исследований Всемирной паутины и академического CS в Великобритании.