Compound assignment на char — рабочий код до символа за границей диапазона
Выглядит невинно: инкремент символа в цикле для генерации диапазона букв. Компилируется, работает на тесте с латиницей — и ломается там, где не ждёшь.
char c = 'z'; c += 1; System.out.println(c);
Здесь ничего не падает — просто печатает {, следующий символ после z в таблице Unicode. Проблема не в этом случае, а в том, что c += 1 — это скрытый каст. Compound assignment оператор в Java всегда включает неявное сужающее преобразование обратно к типу переменной слева.
Развёрнуто это выглядит так: c = (char) (c + 1). Явный каст компилятор вставляет сам, поэтому char c = 'a'; c++; компилируется без единого предупреждения, хотя char d = 'a'; d = d + 1; без каста — ошибка компиляции.
Ловушка возникает, когда диапазон символов формируют программно и не проверяют границу char — от 0 до 65535. Целочисленное переполнение здесь молчаливое: char не кинет исключение, просто перескочит через ноль по модулю 65536.
Что спросят следом: «почему тогда byte b = 10; b += 5; компилируется, а byte b = 10; b = b + 5; — нет?» Ответ: у compound assignment operator есть implicit narrowing cast, встроенный в спецификацию оператора — компилятор сам вставляет (byte) при +=. У обычного присваивания такого каста нет, b + 5 промоутится до int, и int нельзя присвоить byte без явного приведения.
Compound assignment — не сокращение записи, а оператор с собственным поведением приведения типов, которое вы не видите в коде.
Тренажёр: 600 вопросов, мок с таймером, план повторов
senior·base — что спрашивают на самом деле
В этом посте были ссылки, но мы их удалили по правилам Сетки