Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
GoslingJava2.doc
Скачиваний:
140
Добавлен:
23.02.2016
Размер:
2.39 Mб
Скачать

5.11. Порядок вычислений

Язык Java гарантирует, что операнды в операторах вычисляются слева направо. Например, в выражении x+y+z компилятор вычисляет значение x, потом значение y, складывает эти два значения, вычисляет значение z и прибавляет его к предыдущему результату. Компилятор не станет вычислять значение y перед x или z— перед y или x.

Такой порядок имеет значение, если вычисление x, y и z имеет некоторый побочный эффект. Скажем, если при этом будут вызываться методы, которые изменяют состояние объекта или выводят что-нибудь на печать, то изменение порядка вычислений отразится на работе программы. Язык гарантирует, что этого не произойдет.

Все операнды всех операторов, за исключением &&, || и ?: (см. ниже), вычисляются перед выполнением оператора. Это утверждение оказывается истинным даже для тех операций, в ходе которых могут возникнуть исключения. Например, целочисленное деление на ноль приводит к запуску исключения ArithmeticException, но происходит это лишь после вычисления обоих операндов.

5.12. Тип выражения

У каждого выражения имеется определенный тип. Он задается типом компонентов выражения и семантикой операторов. Если арифметический или поразрядный оператор применяется к выражению целого типа, то результат будет иметь тип int, если только в выражении не участвует значение типа long— в этом случае выражение также будет иметь тип long. Все целочисленные операции выполняются с точностью int или long, так что меньшие целые типы short и byte всегда преобразуются в int перед выполнением вычислений.

Если хотя бы один из операндов арифметического оператора относится к типу с плавающей точкой, то при выполнении оператора используется вещественная арифметика. Вычисления выполняются с точностью float, если только по крайней мере один из операндов не относится к типу double; в этом случае вычисления производятся с точностью double, и результат также имеет тип double.

Оператор + выполняет конкатенацию для типа String, если хотя бы один из его операндов относится к типу String или же переменная типа String стоит в левой части оператора +=.

При использовании в выражении значение char преобразуется в int по-средством обнуления старших 16 бит. Например, символ Unicode \uffff является эквивалентом целого значения 0x0000ffff. Несколько иначе рассматривается значение типа short, равное 0xffff,— с учетом знака оно равно –1, поэтому его эквивалент в типе int будет равен 0xffffffff.

5.13. Приведение типов

Java относится к языкам с сильной типизацией— это означает, что во время компиляции практически всегда осуществляется проверка на совместимость типов. Java предотвращает неверные присваивания, запрещая все сколько-нибудь сомнительные операции, и поддерживает механизм приведения типов для тех случаев, когда совместимость может быть проверена только во время выполнения программы. Мы будем рассматривать приведение типов на примере операции присваивания, но все сказанное относится и к преобразованиям внутри выражений, и к присваиванию значений параметрам методов.

5.13.1. Неявное приведение типов

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

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

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

Сохранение диапазона не следует путать с сохранением точности. При некоторых неявных преобразованиях возможна потеря точности. Например, рассмотрим преобразование long в float. Значения floatявляются 32-разрядными, а значения long— 64-разрядными. float содержит меньше значащих цифр, чем long, даже несмотря на то, что этот тип способен хранить числа из большего диапазона. Присваивание значения long переменной типа float может привести к потере данных. Рассмотрим следующий фрагмент:

long orig = 0x7effffffffffffffL;

float fval = orig;

long lose = (long)fval;

System.out.println("orig = " + orig);

System.out.println("fval = " + fval);

System.out.println("losw = " + lose);

Первые два оператора создают значение long и присваивают его переменной float. Чтобы продемонстрировать, что при этом происходит потеря точности, мы производим явное приведение fval к long и присваиваем значение другой переменной (явное приведение типов рассматривается ниже). Результаты, выводимые программой, позволяют убедиться в том, что значение float потеряло часть своей точности, так как значение исходной переменной orig типа long отличается от того, что было получено при явном обратном приведении значения переменной fval к типу long:

orig = 9151314442816847871

fval = 9.15131e+18

lose = 9151314442816847872

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

Значение null может быть присвоено ссылке на объект любого типа, в том числе и ссылке на массив.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]