GrabDuck

Преобразования базовых типов данных | Java

:

Последнее обновление: 30.10.2015

При рассмотрении типов данных указывалось, какие значения может иметь тот или иной тип и сколько байт памяти он может занимать. И мы можем написать, например, так:

byte x = 5;
byte y = x;

Но важно понимать, что это запись не эквивалентна следующей (хотя результат будет тот же):

byte x = 5;
int y = x;

В обоих случаях создается переменная типа byte, которая затем приравнивается другой переменной. Однако если в первом случае это простое приравнивание, а переменная y просто получает значение переменной x, то во втором примере происходит преобразование типов: данные типа byte преобразуются к типу int. Данный тип преобразований называется расширяющим, так как значение типа byte расширяет свой размер до размера типа int. Расширяющие преобразования проходят автоматически и обычно с этим никаких проблем не возникает.

Подобным образом происходит преобразование от типа float к типу double или от типа int к типу long.

Кроме расширяющих преобразований есть еще и сужающие. Сужающие преобразования позволяют привести данные к типу с меньшей разрядностью, например, от типа int, который занимает 4 байта в памяти, к типу byte, который занимает только 1 байт в памяти:

int a = 4;
byte b = a;

Несмотря на то, что значение переменной a - число 4 укладывается в диапазон типа byte, мы все равно получим ошибку. И чтобы безошибочно провести преобразование из одного типа к другому, нам надо применить операцию приведения типов. Суть этой операции состоит в том, что в скобках указывается тип, к которому надо привести данное значение:

int a = 4;
byte b = (byte) a;

Потеря данных при преобразовании

В предыдущей ситуации число 4 вполне укладывалось в диапазон значений типа byte. Но что будет в следующем случае:

int a = 200;
byte b = (byte) a;

Результатом будет число -56. В данном случае число 200 вне диапазона для типа byte (от -128 до 127), поэтому произойдет усечение значения. Так как тип byte предполагает 256 возможных значений, то полученное значение будет равно 200-256, то есть -56.

Усечение рациональных чисел до целых

При преобразовании значений с плавающей точкой к целочисленным значениям, происходит усечение дробной части:

double a = 56.9898;
int b = (int)a;

Здесь значение числа b будет равно 56, несмотря на то, что число 57 было бы ближе к 56.9898. Чтобы избежать подобных казусов, надо применять функцию округления, которая есть в математической библиотеке Java:

double a = 56.9898;
int b = (int)Math.round(a);

Преобразования при операциях

Нередки ситуации, когда приходится применять различные операции, например, сложение и произведение, над значениями разных типов. Здесь также действуют некоторые правила:

  • если один из операндов операции относится к типу double, то и второй операнд преобразуется к типу double

  • если предыдущее условие не соблюдено, а один из операндов операции относится к типу float, то и второй операнд преобразуется к типу float

  • если предыдущие условия не соблюдены, один из операндов операции относится к типу long, то и второй операнд преобразуется к типу long

  • иначе все операнды операции преобразуются к типу int

Например:

int a = 3;
double b = 4.6;
double c = a+b;

Так как в операции участвует значение типа double, то и другое значение приводится к типу double и сумма двух значений a+b будет представлять тип double.

Другой пример:

byte a = 3;
short b = 4;
byte c = (byte)(a+b);

Две переменных типа byte и short (не double, float или long), поэтому при сложении они преобразуются к типу int, и их сумма a+b представляет значение типа int. Поэтому если затем мы присваиваем эту сумму переменной типа byte, то нам опять надо сделать преобразование типов к byte.