Чтение онлайн

на главную - закладки

Жанры

Программирование на Java

Вязовик Н.А.

Шрифт:

Данный пример показывает, что даже простые строки могут содержать многочисленные преобразования, зачастую незаметные для разработчика. Часто бывают и такие случаи, когда программисту необходимо явно изменить тип некоторого выражения или переменной, например, чтобы воспользоваться подходящим методом или конструктором.

Вспомним уже рассмотренный пример:

int b=1;

byte c=(byte)-b;

int i=c;

Здесь во второй строке необходимо провести явное преобразование, чтобы присвоить значение типа int

переменной типа byte. В третьей же строке обратное приведение производится автоматически, неявным для разработчика образом.

Рассмотрим сначала, какие переходы между различными типами можно осуществить.

Виды приведений

В Java предусмотрено семь видов приведений:

* тождественное (identity);

* расширение примитивного типа (widening primitive);

* сужение примитивного типа (narrowing primitive);

* расширение объектного типа (widening reference);

* сужение объектного типа (narrowing reference);

* преобразование к строке (String);

* запрещенные преобразования (forbidden).

Рассмотрим их по отдельности.

Тождественное преобразование

Самым простым является тождественное преобразование. В Java преобразование выражения любого типа к точно такому же типу всегда допустимо и успешно выполняется.

Зачем нужно тождественное приведение? Есть две причины для того, чтобы выделить такое преобразование в особый вид.

Во-первых, с теоретической точки зрения теперь можно утверждать, что любой тип в Java может участвовать в преобразовании, хотя бы в тождественном. Например, примитивный тип boolean нельзя привести ни к какому другому типу, кроме него самого.

Во-вторых, иногда в Java могут встречаться такие выражения, как длинный последовательный вызов методов:

print(getCity.getStreet.getHouse.getFlat.getRoom);

При исполнении такого выражения сначала вызывается первый метод getCity. Можно предположить, что возвращаемым значением будет объект класса City. У этого объекта далее будет вызван следующий метод getStreet. Чтобы узнать, значение какого типа он вернет, необходимо посмотреть описание класса City. У этого значения будет вызван следующий метод ( getHouse ), и так далее. Чтобы узнать результирующий тип всего выражения, необходимо просмотреть описание каждого метода и класса.

Компилятор без труда справится с такой задачей, однако разработчику будет нелегко проследить всю цепочку. В этом случае можно воспользоваться тождественным преобразованием, выполнив приведение к точно такому же типу. Это ничего не изменит в структуре программы, но значительно облегчит чтение кода:

print((MyFlatImpl)(getCity.getStreet.getHouse.getFlat));

Преобразование примитивных типов (расширение и сужение)

Очевидно, что следующие четыре вида приведений легко представляются в виде таблицы 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

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

Поделиться:
Популярные книги

Бастард Императора. Том 12

Орлов Андрей Юрьевич
12. Бастард Императора
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Бастард Императора. Том 12

Законы Рода. Том 12

Андрей Мельник
12. Граф Берестьев
Фантастика:
юмористическое фэнтези
аниме
фэнтези
5.00
рейтинг книги
Законы Рода. Том 12

Кодекс Охотника. Книга XXXIV

Винокуров Юрий
34. Кодекс Охотника
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Кодекс Охотника. Книга XXXIV

Бастард Императора

Орлов Андрей Юрьевич
1. Бастард Императора
Фантастика:
фэнтези
аниме
5.00
рейтинг книги
Бастард Императора

Вечный. Книга II

Рокотов Алексей
2. Вечный
Фантастика:
боевая фантастика
попаданцы
рпг
5.00
рейтинг книги
Вечный. Книга II

Прайм. Рунный призрак

Бор Жорж
3. Легенда
Фантастика:
фэнтези
боевая фантастика
рпг
5.00
рейтинг книги
Прайм. Рунный призрак

Сын Тишайшего

Яманов Александр
1. Царь Федя
Фантастика:
попаданцы
альтернативная история
фэнтези
5.20
рейтинг книги
Сын Тишайшего

Странник

Седой Василий
4. Дворянская кровь
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Странник

Неудержимый. Книга XXXII

Боярский Андрей
32. Неудержимый
Фантастика:
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Неудержимый. Книга XXXII

Идеальный мир для Лекаря 6

Сапфир Олег
6. Лекарь
Фантастика:
фэнтези
юмористическая фантастика
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 6

Третий Генерал: Том XIII

Зот Бакалавр
12. Третий Генерал
Фантастика:
боевая фантастика
фэнтези
аниме
5.00
рейтинг книги
Третий Генерал: Том XIII

Император Пограничья 3

Астахов Евгений Евгеньевич
3. Император Пограничья
Фантастика:
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Император Пограничья 3

Вернуть невесту. Ловушка для попаданки 2

Ардова Алиса
2. Вернуть невесту
Любовные романы:
любовно-фантастические романы
7.88
рейтинг книги
Вернуть невесту. Ловушка для попаданки 2

Бастард Бога (Дилогия)

Матвеев Владимир
Фантастика:
альтернативная история
5.11
рейтинг книги
Бастард Бога (Дилогия)