Menu

Приведение типов в Java: расширение, сужение и преобразования

Как Java преобразует типы: автоматическое расширение, явные сужающие приведения, какие данные теряются при сужении и преобразование между числами и строками.

На этой странице есть исполняемые редакторы: меняйте, запускайте и сразу видите результат.

Что такое приведение типов

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.

Coddy programming languages illustration

Учитесь программировать с Coddy

НАЧАТЬ