Что такое приведение типов
Java — язык со статической типизацией: у каждого значения есть тип, и компилятор не позволит вам незаметно смешивать несовместимые типы. Приведение типов — это способ преобразовать значение из одного типа в другой: иногда Java делает это за вас, а иногда вы должны попросить об этом явно.
Есть два направления. Переход от меньшего типа к большему (из int в double) безопасен и происходит автоматически. Переход от большего типа к меньшему (из double в int) может привести к потере данных, поэтому Java заставляет вас указать это с помощью приведения.
Расширение: автоматическое преобразование
Расширяющее преобразование перемещает значение в тип с большим запасом. Ничего не может быть потеряно, поэтому Java делает это за вас без приведения:
int 7 помещается в double и становится 7.0. Порядок расширения для чисел такой: byte -> short -> int -> long -> float -> double; присваивание слева направо по этой цепочке никогда не требует приведения. Именно поэтому смешивание типов в арифметике часто «просто работает» — Java сначала расширяет меньший операнд.
Сужение: явное приведение
В обратную сторону — сужающее преобразование — может терять данные, поэтому компилятор откажет, если вы не поставите целевой тип в скобках перед значением:
(int) pi — это приведение. Обратите внимание, что оно делает: оно отбрасывает дробную часть в сторону нуля, просто удаляя её. 3.9 становится 3, а -3.9 становится -3. Оно не округляет. Если вам нужно округление — это другой инструмент:
Забыть, что приведение отбрасывает дробную часть, — одна из самых частых ошибок новичков: если ваше «округлённое» число всегда на единицу меньше нужного, обычно причина именно в этом.
Ловушка целочисленного деления
В эту ловушку попадается каждый хотя бы раз. Когда оба операнда — int, оператор / выполняет целочисленное деление и отбрасывает остаток — до того, как произойдёт присваивание в double:
a / b — это 7 / 2, вычисленное полностью в целочисленной арифметике int, что даёт 3. Последующее расширение до double лишь превращает 3 в 3.0 — .5 уже потеряно. Если сначала привести один операнд к double ((double) a / b), всё выражение переходит в арифметику с плавающей точкой и даёт нужное 3.5. Достаточно привести только одну сторону; Java расширит другую, чтобы они совпали.
Когда сужение переполняется
Приведение не проверяет, помещается ли значение. Если оно не помещается, биты просто обрезаются, и вы получаете неожиданный результат — без ошибки, без предупреждения:
300 не помещается в byte, поэтому старшие биты отбрасываются, и вы получаете 44. Это «тихая» потеря данных — программа работает нормально и выдаёт неверный ответ. Сужайте только тогда, когда уверены, что значение помещается в меньший тип.
Преобразование между числами и строками
String — это объект, а не число, поэтому привести его через (int) нельзя — это ошибка компиляции. Для преобразования используются специальные методы:
Для перехода от текста к числу используются Integer.parseInt / Double.parseDouble. Если строка не является корректным числом (например, "hello"), эти методы выбрасывают NumberFormatException. Для перехода от числа к тексту используйте String.valueOf(n) или просто выполните конкатенацию с "" — потому что n + "" заставляет int стать String. Обратите внимание на разницу между "5" + 1 (что даёт строку "51") и 5 + 1 (что даёт 6); + означает конкатенацию в тот момент, когда задействована String.
Приведение объектов
Приведение применяется также к ссылкам на объекты, а не только к примитивам. Вы можете привести ссылку к родственному типу по цепочке наследования — расширение до родительского типа происходит автоматически, а обратное сужение требует явного приведения и безопасно только если объект действительно относится к этому типу:
Object o = "hello";
String s = (String) o; // OK: o действительно ссылается на String
Integer bad = (Integer) o; // компилируется, но во время выполнения выбрасывает ClassCastException
Второе приведение компилируется, но падает во время выполнения с ClassCastException, потому что объект — это String, а не Integer. По-настоящему вы столкнётесь с этим, когда дойдёте до наследования и полиморфизма; пока же достаточно знать, что синтаксис (Type) — это та же идея, применённая к объектам.
Далее: if-else
Приведение позволяет преобразовывать значения; следующий шаг — заставить вашу программу выбирать между путями на основе этих значений. Оператор if-else выполняет один блок, когда условие истинно, и другой, когда оно ложно — основа любого решения, которое принимает ваш код. Это следующая страница.
Часто задаваемые вопросы
Что такое приведение типов в Java?
Приведение типов — это преобразование значения из одного типа данных в другой. Java выполняет небольшие «расширяющие» преобразования автоматически (например, из int в double), но «сужающее» преобразование, при котором данные могут быть потеряны (например, из double в int), требует явного приведения: int n = (int) 3.9;.
Как преобразовать double в int в Java?
Поставьте целевой тип в скобках перед значением: int n = (int) 3.9;. Это отбрасывает дробную часть в сторону нуля, поэтому вы получаете 3, а не 4. Чтобы вместо этого округлить, используйте Math.round(3.9), который возвращает 4.
Как преобразовать String в int в Java?
String — это не число, поэтому привести его через (int) нельзя. Используйте Integer.parseInt("42"), чтобы получить int, или Double.parseDouble("3.14") для double. Если текст не является корректным числом, эти методы выбрасывают NumberFormatException.