Глава 5.4. Преобразования типов5.4.1. Виды преобразованийКаждое выражение в Java имеет тип, который определяется структурой выражения и типами составляющих его операндов (констант, переменных и методов). Однако, иногда нам может потребоваться явное преобразование выражения в другой тип. Кроме того, в некоторых ситуациях исполняющая система Java сама неявно проводит такие преобразования. Преобразование типа Т1 в тип T2 позволяет выражению типа T1 трактоваться в период компиляции как выражение типа T2. В одних случаях это чисто синтаксическая конструкция, не влияющая на генерируемый код, в других преобразование типа требует дополнительных действий в период выполнения по изменению значения выражения или дополнительных проверок правильности применяемого преобразования. Примеры:
Далее в этой главе приведена классификация всех возможных преобразований типов, а затем классификация контекстов в которой они могут использоваться. 5.4.1.1. Расширяющие преобразования чиселРасширяющие преобразования чисел это преобразования числового типа в "больший" числовой тип, которые считаются безопасными, т. к. не приводят к потере величины преобразуемого значения. Такими преобразованиями в Java являются:
В действительности, преобразование целого значения в плавающее может привести к потере точности, т. е. к потере значащих цифр. Так, следующий пример class Test { public static void main(String args[]) { int bigNumber = 1234567890; float approximate = bigNumber; System.out.println(approximate); } } выведет на экран строку 1234567936. Это связано с тем, что при преобразовании int в float результирующее значение равно 1.2345679E9 из-за того, что мантисса чисел типа float вмещает только 8 десятичных цифр (здесь для правильной работы следует использовать преобразование к типу double). Тем не менее, исполняющая система никогда не генерирует ошибок при выполнении перечисленных преобразований. 5.4.1.2. Сужающие преобразования чиселСужающие преобразования чисел это преобразования числового типа в "меньший" числовой тип, которые могут привести как к потере величины, так и к потере точности. Такими преобразованиями в Java являются:
Мы не будем здесь подробно рассматривать правила, по которым происходят эти преобразования, поскольку интуитивно они понятны, а формально достаточно громоздки. При их применении важно помнить, что Java, в отличие от других языков, не генерирует ошибок при переполнении (overflow) или потере значения (underflow), поэтому контроль за корректностью преобразований полностью ложится на программиста. 5.4.1.3. Расширяющие преобразования ссылокРасширяющие преобразования ссылок это преобразования производных ссылочных типов в типы их предков, которые не требуют никаких действий на этапе исполнения и никогда не генерируют ошибок. Такими преобразованиями в Java являются:
5.4.1.4. Сужающие преобразования ссылокСужающие преобразования ссылок это преобразования производных ссылочных типов в типы их потомков. Эти преобразования требуют проверки своей легитимности на этапе исполнения и могут генерировать исключение ClassCastException. Такими преобразованиями в Java являются:
5.4.1.5. Преобразования в строкиЛюбое выражение в Java, включая null, может быть преобразовано в тип String. 5.4.1.6. Недопустимые преобразованияСледующие преобразования типов в Java запрещены:
5.4.2. Контексты преобразований5.4.2.1. Преобразование при присваиванииПреобразование при присваивании происходит, когда значение выражения присваивается переменной. При этом тип выражения преобразуется к типу переменной. При присваивании всегда возможны расширяющие преобразования типов (как числовых, так и ссылочных). Сужающее преобразование возможно только при соблюдении следующих условий:
Например, оператор Если тип выражения не может быть преобразован к типу переменной, то компилятор генерирует ошибку. В остальных случаях мы говорим, что тип выражения совместим по присваиванию с типом переменной. Так, следующий фрагмент short s = 123; char c = s; // генерирует ошибку компиляции приведет к генерации ошибки, поскольку типы char и short несовместимы по присваиванию согласно данных выше определениям (первый реализован 16-битовыми словами без знака, а второй со знаком). 5.4.2.2. Преобразование аргументов методаПреобразование аргументов метода происходит, когда фактические значения аргументов преобразуется к типу параметров метода или конструктора при его вызове. При этом всегда возможны расширяющие преобразования типов (как числовых, так и ссылочных) и недопустимы сужающие преобразования. Причины последнего запрета можно пояснить следующим примером: class Test { static int m(byte a, int b) { return a + b; } static int m(short a, short b) { return a - b; } public static void main(String args[]) { System.out.println(m(1, 2)); // генерирует ошибку компиляции } } Здесь класс Test содержит два одноименных метода, которые различаются только типами
параметров. Если бы сужающие преобразования аргументов были в Java разрешены, то исполняющей
системе пришлось бы определять, к какому из этих методов относится вызов 5.4.2.3. Преобразование в строкуПреобразование в строку происходит только в одном случае: когда бинарная операция + применяется к двум операндам, один из которых имеет тип String. В этой ситуации второй операнд также преобразуется к типу String, и результатом операции является конкатенация полученных строк. Подробнее этот процесс описан в гл. 5.14. 5.4.2.4. Явное преобразование типаЯвное преобразование типа происходит, когда к операнду явно применяется операция приведения типа (type cast). В этой ситуации могут применяться все описанные выше виды преобразований типов, кроме преобразования в строку. Попытка явного преобразования к типу, отмеченная выше, как запрещенная, вызовет ошибку компиляции. Кроме того, на этапе выполнения возможна генерация исключения ClassCastException, если заданное преобразование недопустимо. 5.4.3. Преобразования типов числовых операндовПреобразование типов в процессе вычисления числовых выражений имеет ряд особенностей. Они сводятся к двум случаям: преобразования операндов в унарных операциях и в бинарных операциях. Перед выполнением унарной операции:
Перед выполнением бинарной операции:
|