Смекни!
smekni.com

Общие представления о языке Java 5 (стр. 23 из 68)

3.7.Приоритет операторов

При вычислении выражений важен приоритет операторов. Для операторов сложения, вычитания, умножения и деления он “естественный”: умножение и деление обладают одинаковым наиболее высоким приоритетом, а сложение и вычитание – одинаковым приоритетом, который ниже. Таким образом, например,

a*b/c+d

это то же, что

( (a*b)/c )+d

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

(a+b)*c будет вычисляться так: сначала вычислится сумма a+b, после чего полученный результат будет умножен на значение c.

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

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

Приори-тет
Группа операторов

Операторы

1 высший Постфиксные

( )

[ ]

.

2 Унарные

++ операнд

операнд ++

--операнд

операнд--

~

!

+ операнд - операнд
3 Создания объектов и преобразования типа

new

(тип) операнд

4 Мультипликатив-ные

*

/

%

5 Аддитивные

+

-

6 Сдвиги битов

>>

>>>

<<

7 Отношения

>

>=

<

<=

instanceof
8 Эквивалентности

==

!=

9 Побитовое И

&

10 Побитовое исключающее ИЛИ

^

11 Побитовое ИЛИ

|

12 Логическое И

&&

13 Логическое ИЛИ

||

14 Условный

? :

15 низший Присваивания

=

Оператор= ( +=, -=, *=, /= и т.п. )

3.8.Типы-перечисления (enum)

Иногда требуется использовать элементы, которые не являются ни числами, ни строками, но ведут себя как имена элементов и одновременно обладают порядковыми номерами. Например, названия месяцев или дней недели. В этих случаях используют перечисления. Для задания типа какого-либо перечисления следует написать зарезервированное слово enum (сокращение от enumeration – “перечисление”), после которого имя задаваемого типа, а затем в фигурных скобках через запятую элементы перечисления. В качестве элементов можно использовать любые простые идентификаторы (не содержащие квалификаторов вида имя1.имя2).

Тип-перечисление обязан быть глобальным – он может задаваться либо на уровне пакета, либо в каком-либо классе. Но его нельзя задавать внутри какого-либо метода. Элементы перечисления могут иметь любые имена, в том числе совпадающие в разных перечислениях или совпадающие с именами классов или их членов – каждое перечисление имеет своё собственное пространство имён. Доступ к элементу перечисления осуществляется с квалификацией именем типа-перечисления:

ИмяТипа.имяЭлемента

У каждого элемента перечисления имеется порядковый номер, соответствующий его положению в наборе - нумерация начинается с нуля. Поэтому первый элемент имеет номер 0, второй элемент – номер 1, и так далее. Имеется функция ordinal(), возвращающая порядковый номер элемета в перечислении. Также имеется функция compareTo, позволяющая сравнивать два элемента перечисления - она возвращает разницу в их порядковых номерах.

Строковое представление значения можно получить с помощью функции name(). Преобразование из строки в значение типа “перечисление” осуществляется с помощью функции класса valueOf, в которую передаётся строковое представление значения.

Если требуется рассматривать элементы перечисления как массив, можно воспользоваться функцией values() – она возвращает массив элементов, к которым можно обращаться по индексу. Формат вызова функции такой: ИмяТипа.values()

Для примера зададим типы-перечисления Monthes (“месяцы”) и Spring (“весна”), соответствующие различным наборам месяцев:

enum Monthes {jan,feb,mar,apr,may,jun,jul,aug,sept,oct,nov,dec};

enum Spring { march, apr, may };

Названия месяцев мы намеренно пишем со строчной буквы для того, чтобы было понятно, что это идентификаторы переменных, а не типы. А имя марта написано по-разному в типах Monthes и Spring для того, чтобы показать независимость их пространств имён.

Объявление переменных типа “перечисление” делается так же, как для всех остальных типов, при этом переменные могут быть как неинициализированы, так и инициализированы при задании:

public Monthes m1 ,m2=Monthes.mar, m3;

- при задании в классе общедоступных полей m1, m2 и m3,

Spring spr1=Spring.apr, spr2;

- при задании в методе локальной переменной или задании в классе поля spr1 с пакетным уровнем доступа.

После чего возможны следующие операторы:

spr2=spr1;

spr1=Spring.may;

System.out.println("Результат сравнения="+spr2.compareTo(Spring.march));

После выполнения этих операторов в консольное окно будет выведен текст

Результат сравнения=1 ,

поскольку в переменной spr2 окажется значение Spring.apr , порядковый номер которого на 1 больше, чем у значения Spring.march , с которым идёт сравнение.

Пусть в переменной spr2 хранится значение Spring.may. Порядковый номер значения, хранящегося в переменной, можно получить с помощью вызова spr2.ordinal() . Он возвратит число 2, так как may – третий элемент перечисления (сдвиг на 1 получается из-за того, что нумерация начинается с нуля).

Строковое представление значения, хранящегося в переменной spr2, можно получить с помощью вызова spr2.name() . Он возвратит строку “may” - имя типа в возвращаемое значение не входит.

Если переменная типа “перечисление” не инициализирована, в ней хранится значение null. Поэтому вызов

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

осуществлённый до присваивания переменной spr2 значения возвратит строку

spr2=null

А вот попытки вызовов spr2.ordinal() или spr2.name() приведут к возникновению ошибки (исключительной ситуации) с диагностикой

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException

Получение значения типа Spring по номеру, хранящемуся в переменной i, осуществляется так:

spr1=Spring.values()[i];

Преобразование из строки в значение типа Spring будет выглядеть так:

spr1=Spring.valueOf("march");

Краткие итоги по главе 3

- Величины типа boolean принимают значения true или false.

- Логические операторы && -“И”, || - “ИЛИ”, ^ - “Исключающее ИЛИ”, ! – “НЕ” применимы к величинам булевского типа. Логические выражения в Java вычисляются в соответствии с укороченным оцениванием.

- Операторы сравнения применимы к любым величинам a и b одного типа, а также к произвольным числовым величинам a и b, не обязательно имеющим один тип. В качестве оператора сравнения на равенство используется составной символ, состоящий из двух подряд идущих символа равенства “==”.

- В Java имеются встроенные примитивные целые типы byte, short, int, long и символьный тип char, в некотором смысле также являющийся целочисленным. При этом только тип char беззнаковый, все остальные – знаковые.

- Для задания в тексте программы численных литерных констант типа long, выходящих за пределы диапазона чисел типа int, после написания числа следует ставить постфикс – букву L.

- Константами называются именованные ячейки памяти с неизменяемым содержимым. Объявление констант осуществляется в классе, при этом перед именем типа константы ставится комбинация зарезервированных слов public и final.

- В Java имеется два встроенных примитивных вещественных типа float и double (точнее, типы чисел в формате с плавающей точкой).

- Математические функции, а также константы “пи” (Math.PI) и “е” (Math.E ) заданы в классе Math, находящемся в пакете java.lang .

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

- При работе с вещественными величинами в Java возможна работа на аппаратном уровне только с операндами типов float и double. Если один из операндов имеет тип double, а другой float, действия производятся с числами типа double, поскольку операнд типа float автоматически преобразуется к типу double.