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

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

Жанры

Программирование на Java
Шрифт:

Повторим этот пример:

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:

char c=40000;

print((short)c);

Результатом будет:

– 25536

Сужение дробного типа до целочисленного является более сложной процедурой. Она проводится в два этапа.

На первом шаге дробное значение преобразуется в long, если целевым типом является long, или в int - в противном случае (целевой тип byte, short, char или int ). Для этого исходное дробное число сначала математически округляется в сторону нуля, то есть дробная часть просто отбрасывается.

Например, число 3,84 будет округлено до 3, а -3,84 превратится в -3. При этом могут возникнуть особые случаи:

* если исходное дробное значение является NaN, то результатом первого шага будет 0 выбранного типа (т.е. int или long );

* если исходное дробное значение является положительной или отрицательной бесконечностью, то результатом первого шага будет, соответственно, максимально или минимально возможное значение для выбранного типа (т.е. для int или long );

* наконец, если дробное значение было конечной величиной, но в результате округления получилось слишком большое по модулю число для выбранного типа (т.е. для int или long ), то, как и в предыдущем пункте, результатом первого шага будет, соответственно, максимально или минимально возможное значение этого типа. Если же результат округления укладывается в диапазон значений выбранного типа, то он и будет результатом первого шага.

На втором шаге производится дальнейшее сужение от выбранного целочисленного типа к целевому, если таковое требуется, то есть может иметь место дополнительное преобразование от int к byte, short или char.

Проиллюстрируем описанный алгоритм преобразованием от бесконечности ко всем целочисленным типам:

float fmin = Float.NEGATIVE_INFINITY;

float fmax = Float.POSITIVE_INFINITY;

print("long: " + (long)fmin + ".." + (long)fmax);

print("int: " + (int)fmin + ".." + (int)fmax);

print("short: " + (short)fmin + ".." + (short)fmax);

print("char: " + (int)(char)fmin + ".." + (int)(char)fmax);

print("byte: " + (byte)fmin + ".." + (byte)fmax);

Результатом

будет:

long: -9223372036854775808..9223372036854775807

int: -2147483648..2147483647

short: 0..-1

char: 0..65535

byte: 0..-1

Значения long и int вполне очевидны - дробные бесконечности преобразовались в, соответственно, минимально и максимально возможные значения этих типов. Результат для следующих трех типов ( short, char, byte ) есть, по сути, дальнейшее сужение значений, полученных для int, согласно второму шагу процедуры преобразования. А делается это, как было описано, просто за счет отбрасывания старших битов. Вспомним, что минимально возможное значение в битовом виде представляется как 1000..000 (всего 32 бита для int, то есть единица и 31 ноль). Максимально возможное - 1111..111 (32 единицы). Отбрасывая старшие биты, получаем для отрицательной бесконечности результат 0, одинаковый для всех трех типов. Для положительной же бесконечности получаем результат, все биты которого равняются 1. Для знаковых типов byte и short такая комбинация рассматривается как -1, а для беззнакового char - как максимально возможное значение, то есть 65535.

Может сложиться впечатление, что для char приведение дает точное значение. Однако это был частный случай - отбрасывание битов в большинстве случаев все же дает искажение. Например, сужение дробного значения 2 миллиарда:

float f=2e9f;

print((int)(char)f);

print((int)(char)-f);

Результатом будет:

37888

27648

Обратите внимание на двойное приведение для значений типа char в двух последних примерах. Понятно, что преобразование от char к int не приводит к потере точности, но позволяет распечатывать не символ, а его числовой код, что более удобно для анализа.

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

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

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

// Объявляем класс Parent

class Parent {

int x;

}

// Объявляем класс Child и наследуем

// его от класса Parent

class Child extends Parent {

int y;

}

// Объявляем второго наследника

// класса Parent - класс Child2

class Child2 extends Parent {

int z;

}

В каждом классе объявлено поле с уникальным именем. Будем рассматривать это поле как пример набора уникальных свойств, присущих некоторому объектному типу.

Три объявленных класса могут порождать три вида объектов. Объекты класса Parent обладают только одним полем x, а значит, только ссылки типа Parent могут ссылаться на такие объекты. Объекты класса Child обладают полем y и полем x, полученным по наследству от класса Parent. Стало быть, на такие объекты могут указывать ссылки типа Child или Parent. Второй случай уже иллюстрировался следующим примером:

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

Вдовье счастье

Брэйн Даниэль
1. Ваш выход, маэстро!
Фантастика:
попаданцы
историческое фэнтези
фэнтези
5.00
рейтинг книги
Вдовье счастье

Крепость над бездной

Лисина Александра
4. Гибрид
Фантастика:
боевая фантастика
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Крепость над бездной

Прорвемся, опера! Книга 4

Киров Никита
4. Опер
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Прорвемся, опера! Книга 4

Возвышение Меркурия. Книга 12

Кронос Александр
12. Меркурий
Фантастика:
героическая фантастика
попаданцы
аниме
5.00
рейтинг книги
Возвышение Меркурия. Книга 12

Черный дембель. Часть 2

Федин Андрей Анатольевич
2. Черный дембель
Фантастика:
попаданцы
альтернативная история
4.25
рейтинг книги
Черный дембель. Часть 2

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

Винокуров Юрий
15. Кодекс Охотника
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Кодекс Охотника. Книга XV

Как я строил магическую империю

Зубов Константин
1. Как я строил магическую империю
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Как я строил магическую империю

Звездная Кровь. Изгой

Елисеев Алексей Станиславович
1. Звездная Кровь. Изгой
Фантастика:
боевая фантастика
попаданцы
рпг
5.00
рейтинг книги
Звездная Кровь. Изгой

Камень. Книга 3

Минин Станислав
3. Камень
Фантастика:
фэнтези
боевая фантастика
8.58
рейтинг книги
Камень. Книга 3

Монстр из прошлого тысячелетия

Еслер Андрей
5. Соприкосновение миров
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Монстр из прошлого тысячелетия

Найди меня Шерхан

Тоцка Тала
3. Ямпольские-Демидовы
Любовные романы:
современные любовные романы
короткие любовные романы
7.70
рейтинг книги
Найди меня Шерхан

Релокант

Ascold Flow
1. Релокант в другой мир
Фантастика:
фэнтези
попаданцы
рпг
5.00
рейтинг книги
Релокант

Мужчина моей судьбы

Ардова Алиса
2. Мужчина не моей мечты
Любовные романы:
любовно-фантастические романы
8.03
рейтинг книги
Мужчина моей судьбы

Ученик. Книга вторая

Первухин Андрей Евгеньевич
2. Ученик
Фантастика:
фэнтези
5.40
рейтинг книги
Ученик. Книга вторая