Преобразование примитивных типов (расширение и сужение)
Очевидно, что следующие четыре вида приведений легко представляются в виде таблицы 7.1.
Таблица 7.1. Виды приведений.простой тип, расширениессылочный тип, расширениепростой тип, сужениессылочный тип, сужение
Что все это означает? Начнем по порядку. Для простых типов расширение означает, что осуществляется переход от менее емкого типа к более емкому. Например, от типа byte (длина 1 байт) к типу int (длина 4 байта). Такие преобразования безопасны в том смысле, что новый тип всегда гарантированно вмещает в себя все данные, которые хранились в старом типе, и таким образом не происходит потери данных. Именно поэтому компилятор осуществляет его сам, незаметно для разработчика:
byte b=3; int a=b;
В последней строке значение переменной b типа byte будет преобразовано к типу переменной a (то есть, int ) автоматически, никаких специальных действий для этого предпринимать не нужно.
Следующие 19 преобразований являются расширяющими:
от byte к short, int, long, float, double
от short к int, long, float, double
от char к int, long, float, double
от int к long, float, double
от long к float, double
от float к double
Обратите внимание, что нельзя провести преобразование к типу char от типов меньшей или равной длины ( byte, short ), или, наоборот, к short от char без потери данных. Это связано с тем, что char, в отличие от остальных целочисленных типов, является беззнаковым.
Тем не менее, следует помнить, что даже при расширении данные все-таки могут быть в особых случаях искажены. Они уже рассматривались в предыдущей лекции, это приведение значений int к типу float и приведение значений типа long к типу float или double. Хотя эти дробные типы вмещают гораздо большие числа, чем соответствующие целые, но у них меньше значащих разрядов.
Повторим этот пример:
long a=111111111111L; float f = a; a = (long) f; print(a);
Результатом будет:
111111110656
Обратное преобразование - сужение - означает, что переход осуществляется от более емкого типа к менее емкому. При таком преобразовании есть риск потерять данные. Например, если число типа int было больше 127, то при приведении его к byte значения битов старше восьмого будут потеряны. В Java такое преобразование должно совершаться явным образом, т.е. программист в коде должен явно указать, что он намеревается осуществить такое преобразование и готов потерять данные.
Следующие 23 преобразования являются сужающими:
от byte к char
от short к byte, char
от char к byte, short
от int к byte, short, char
от long к byte, short, char, int
от float к byte, short, char, int, long
от double к byte, short, char, int, long, float
При сужении целочисленного типа к более узкому целочисленному все старшие биты, не попадающие в новый тип, просто отбрасываются. Не производится никакого округления или других действий для получения более корректного результата:
print((byte)383); print((byte)384); print((byte)-384);
Результатом будет:
127 -128 -128
Видно, что знаковый бит при сужении не оказал никакого влияния, так как был просто отброшен - результат приведения обратных чисел (384 и -384) оказался одинаковым. Следовательно, может быть потеряно не только точное абсолютное значение, но и знак величины.
Это верно и для типа char: