Все разделы
Выбрать школу

Школа. Увлечения. Большое будущее.

PROSCHOOLS · ОБРАЗОВАНИЕ РЯДОМ

Ваш город

Выберите город, чтобы находить образование и возможности рядом.

Как учитываем городКаталог и кнопки «Выбрать школу» покажут школы выбранного города.Онлайн-курсы, учебник, ГДЗ и задания к экзаменам доступны по всей России.

Популярные города

Будет выбран: Вся Россия

Учебные материалы останутся прежними.

Поиск по сайту

По всему сайтуШколы выбранного города — выше в результатах

С чего начнём?

↑ ↓ — выбрать результат · Enter — открыть · Esc — закрыть

Приведение типов в Java: учебные примеры и ошибки школьника

💻 Информатика · 10 класс

Как школьнику разобраться в расширении, сужении и cast в Java. Округление, byte, деление, строки и объекты: разобранные примеры и пять заданий с ответами.

Клавиатура в компьютерном классе
Иллюстрация к предмету «Информатика»Hmartil · Wikimedia Commons · CC BY-SA 4.0

В первых школьных программах на Java важно различать тип исходного значения и тип результата. Например, запись среднего балла в переменную double ещё не делает деление дробным. Этот урок для школьников разбирает расширение, сужение и явное приведение — cast. В спецификации Java существуют и другие преобразования, включая boxing и unboxing; классификация не ограничивается двумя видами. Примеры относятся к правилам Java SE 17.

Расширяющие преобразования: когда Java всё делает сама

Расширяющие числовые преобразования допустимы неявно в подходящем контексте, например при присваивании. Но название «расширение» не гарантирует сохранения точного значения при переходе из целых чисел в числа с плавающей точкой. Допустимые направления показаны ниже:

ИзВ (неявное расширение)
byteshort, int, long, float, double
short, charint, long, float, double
intlong, float, double
longfloat, double
floatdouble

Тип char расширяется до int по коду символа в Unicode: 'A' имеет код 65, поэтому 'A' + 2 — это уже арифметика над int и даёт 67. При переходах int → float, long → float и long → double возможно округление. Например, int 16777217 после преобразования к float представляется как 16777216: в этом диапазоне соседние значения float уже не различают каждое целое. Поэтому для количества предметов или точных счётчиков не стоит выбирать дробный тип только потому, что он считается «шире».

Сужающие преобразования и потеря данных

При сужении обычно нужен явный cast: (тип) значение. Для присваивания допустимой константы есть исключение: byte count = 42; компилируется без cast, потому что значение константы помещается в byte. Но int count = 42; byte small = count; без cast недопустимо: обычная переменная int не является константным выражением. Разные виды сужения работают по разным правилам, а не всегда просто отбрасывают биты.

Пример 1. Переполнение byte. Тип byte занимает 8 бит и хранит диапазон от −128 до 127. Код byte b = (byte) 130; компилируется, а на этапе выполнения лишние биты отбрасываются по модулю 256: значение 130 выходит за верхнюю границу на 2, поэтому в b окажется −126 (130 − 256). Аналогично (byte) 200 даст −56. При таком числовом приведении исключение не возникает: результат определяется младшими восемью битами. По одному успешному выполнению нельзя судить, что исходное число сохранилось.

Пример 2. Отбрасывание дробной части. Выражение int n = (int) 9.99; даёт 9, а не 10: при сужении double к целому дробная часть отбрасывается с округлением к нулю (для −9.99 результат −9). Для обычного округления до ближайшего целого есть Math.round со своими правилами; результат зависит от выбранного метода. Приведённые примеры усечения относятся к конечным числам в диапазоне int. Для NaN результат приведения к int равен 0, а значения за границами диапазона, включая бесконечности, приводятся к соответствующей граничной величине int.

Приведение внутри выражений

Правила cast не отменяют правила вычисления выражений. В строке double d = 1 / 2; деление выполняется до присваивания, оба операнда — int, поэтому результат 0, который затем неявно расширяется до 0.0. Чтобы получить 0.5, нужно расширить один из операндов заранее: 1.0 / 2 или (double) 1 / 2. Порядок имеет значение: (double) (1 / 2) даёт ровно 0.0, потому что сначала выполняется целочисленное деление, а cast применяется уже к его результату.

Строки и числа: это не приведение типов

Строка в Java — объект, и между String и числами нет cast. Преобразование выполняют методы: Integer.parseInt("12") возвращает примитив int 12, Double.parseDouble("2.5") — double 2.5. Метод Integer.valueOf("12") разбирает строку и возвращает объект Integer. В арифметическом выражении такой объект может неявно распаковываться в int. Сам вызов valueOf со строкой не следует путать с boxing-преобразованием уже имеющегося примитивного значения. Некорректная строка ("abc", "4,2" с запятой) вызовет NumberFormatException, поэтому данные от пользователя преобразуют с проверкой или обработкой исключения. Обратно: String.valueOf(42) или конкатенация 42 + "" дают строку "42".

Приведение объектных типов: upcast и downcast

При приведении ссылочного выражения меняется его тип для дальнейшего использования; сам объект не превращается в объект другого класса. Расширяющий upcast автоматичен: Object obj = "строка"; — строка везде, где ждут Object. Обратный downcast требует cast: String s = (String) obj;. Если фактический объект другого типа, выполнение завершится ошибкой ClassCastException, поэтому безопасный стиль — проверка instanceof:

Object obj = Integer.valueOf(5);
if (obj instanceof String) {
    String s = (String) obj; // сюда не попадём
} else {
    System.out.println("Это не строка");
}

Приведение к параметризованным типам возможно, но из-за стирания типов часть таких преобразований проверяется не полностью и вызывает предупреждения компилятора. Нельзя считать cast способом проверить тип каждого элемента коллекции. Подробнее — в материале о generics в Java, а про встречающиеся рядом преобразования примитивов в объекты — boxing и unboxing.

Упражнения

Задание 1

Чему равно выражение (int) 3.99 и почему не 4?

Ответ 1: 3. Явное приведение double к int отбрасывает дробную часть (округление к нулю), а не округляет по математическим правилам.

Задание 2

Что выведет код byte b = (byte) 200; System.out.println(b);?

Ответ 2: −56. Диапазон byte — от −128 до 127; значение 200 выходит за границу на 72, и по модулю 256 получается 200 − 256 = −56.

Задание 3

Чему равно значение выражения 'A' + 2?

Ответ 3: 67. Символ 'A' имеет код 65 в Unicode; в арифметическом выражении char автоматически расширяется до int, и 65 + 2 = 67.

Задание 4

Чему равно double d = 5 / 2; и как получить 2.5?

Ответ 4: 2.0: сначала выполняется целочисленное деление 5 / 2 = 2, затем 2 неявно расширяется до 2.0. Результат 2.5 дают выражения 5.0 / 2 или (double) 5 / 2 — cast должен попасть на операнд до деления.

Задание 5

Как преобразовать строку "12" в число и прибавить к нему 3?

Ответ 5: int n = Integer.parseInt("12") + 3;, результат 15. Оператор (int) для строк не работает — нужен метод parseInt, который при нечисловой строке бросит NumberFormatException.

Источники и материалы