1 2
Беззнаковый
сдвиг вправо
Часто требуется, чтобы при
сдвиге вправо расширение знакового разряда
не происходило, а освобождающиеся левые
разряды просто заполнялись бы нулями.
class ByteUShift
{
static public void
main(String args[]) {
char
hex[] = { '0',
'1’, '2', '3', '4', '5',
'6', '7', '8', '9', 'а', 'b', 'с', 'd',
'e', 'f’ };
byte b =
(byte) 0xf1;
byte c =
(byte) (b
>> 4);
byte d =
(byte) (b
>> 4);
byte e =
(byte) ((b
& 0xff) >> 4);
System.out.println("
b = 0x" + hex(b >> 4) & 0x0f] + hex[b & 0x0f]);
System.out.println(“
b >> 4 = 0x" + hex[(c
>> 4) & 0x0f] + hex[c & 0x0f]);
System.out.println(“b
>>> 4 = 0x" + hex[(d >> 4) & 0x0f] + hex[d &
0x0f]);
System.out.println(“(b
& 0xff) >> 4 = 0x" + hex[(e >> 4) & 0x0f] + hex[e
& 0x0f]);
} }
Для этого примера переменную b
можно было бы инициализировать
произвольным отрицательным числом, мы
использовали число с шестнадцатиричным
представлением 0xf1. Переменной с
присваивается результат знакового
сдвига b вправо на 4 разряда. Как и
ожидалось, расширение знакового разряда
приводит к тому, что 0xf1 превращается в 0xff.
Затем в переменную d заносится результат
беззнакового сдвига b вправо на 4 разряда.
Можно было бы ожидать, что в результате d содержит
0x0f, однако на деле мы снова получаем 0xff. Это
— результат расширения знакового разряда,
выполненного при автоматическом повышении
типа переменной b до int перед операцией
сдвига вправо. Наконец, в выражении для
переменной е нам удается добиться
желаемого результата — значения 0x0f. Для
этого нам пришлось перед сдвигом вправо
логически умножить значение переменной b
на маску 0xff, очистив таким образом
старшие разряды, заполненные при
автоматическом повышении типа. Обратите
внимание, что при этом уже нет необходимости
использовать беззнаковый сдвиг вправо,
поскольку мы знаем состояние знакового
бита после операции AND.
С:
\> java ByteUShift
b = 0xf1
b >> 4
= 0xff
b >>> 4 = 0xff
b & 0xff) >>
4 = 0x0f
Битовые операторы присваивания
Так же, как и в случае
арифметических операторов, у всех
бинарных битовых операторов есть
родственная форма, позволяющая
автоматически присваивать результат
операции левому операнду. В следующем
примере создаются несколько целых
переменных, с которыми с помощью
операторов, указанных выше, выполняются
различные операции.
class OpBitEquals {
public static void
main(String args[]) {
int a = 1;
int b = 2;
int с = 3;
a |= 4;
b >>= 1;
с <<= 1;
а ^= с;
System.out.println("a
= " + a);
System.out.println("b
= " + b);
System.out.println("c
= " + c);
} }
Результаты исполнения
программы таковы:
С:\>
Java OpBitEquals
а = 3
b = 1
с = 6
Операторы
отношения
Для того, чтобы можно было
сравнивать два значения, в Java имеется
набор операторов, описывающих отношение и
равенство. Список таких операторов
приведен в таблице.
|
Оператор
|
Результат
|
|
==
|
равно
|
|
!=
|
не равно
|
|
>
|
больше
|
|
<
|
меньше
|
|
>=
|
больше или равно
|
|
<=
|
меньше или равно
|
Значения любых типов, включая
целые и вещественные числа, символы,
логические значения и ссылки, можно
сравнивать, используя оператор проверки
на равенство == и неравенство !=. Обратите
внимание — в языке Java, так же, как в С и C++
проверка на равенство обозначается
последовательностью (==). Один знак (=) — это
оператор присваивания.
Булевы
логические операторы
Булевы логические операторы,
сводка которых приведена в таблице ниже,
оперируют только с операндами типа boolean.
Все бинарные логические операторы
воспринимают в качестве операндов два
значения типа boolean и возвращают результат
того же типа.
|
Оператор
|
Результат
|
Оператор
|
Результат
|
|
&
|
логическое И (AND)
|
&=
|
И (AND) с присваиванием
|
|
|
|
логическое ИЛИ (OR)
|
=
|
ИЛИ (OR) с присваиванием
|
|
^
|
логическое исключающее ИЛИ
(XOR)
|
^=
|
исключающее ИЛИ (XOR) с
присваиванием
|
|
||
|
оператор OR быстрой оценки
выражений (short circuit OR)
|
==
|
равно
|
|
&&
|
оператор AND быстрой оценки
выражений (short circuit AND)
|
!=
|
не равно
|
|
!
|
логическое унарное
отрицание (NOT)
|
?:
|
тернарный оператор if-then-else
|
Результаты воздействия
логических операторов на различные комбинации
значений операндов показаны в таблице.
|
А
|
В
|
OR
|
AND
|
XOR
|
NOT A
|
|
false
|
false
|
false
|
false
|
false
|
true
|
|
true
|
false
|
true
|
false
|
true
|
false
|
|
false
|
true
|
true
|
false
|
true
|
true
|
|
true
|
true
|
true
|
true
|
false
|
false
|
Программа,
приведенная ниже, практически полностью
повторяет уже знакомый вам пример BitLogic. Только но
на этот раз мы работаем с булевыми
логическими значениями.
class BoolLogic {
public static void
main(String args[]) {
boolean a =
true;
boolean b =
false;
boolean с = a |
b;
boolean d = a &
b;
boolean e = a ^
b;
boolean f =
(!a &
b) | (a & !b);
boolean g =
!a;
System.out.println("
a = " + a);
System.out.println("
b = " + b);
System.out.println("
a|b = " + c);
System.out.println("
a&b = " + d);
System.out.println("
a^b = " + e);
System.out.println("!a&b|a&!b
= " + f);
System.out.println("
!a = " + g);
} }
С:
\> Java BoolLogic
а = true
b = false
a|b = true
a&b = false
a^b = true
!a&b|a&!b =
true
!a = false
Операторы
быстрой оценки логических выражений (short
circuit logical operators)
Существуют два
интересных дополнения к набору логических
операторов. Это — альтернативные версии
операторов AND и OR, служащие для быстрой
оценки логических выражений. Вы знаете,
что если первый операнд оператора OR имеет
значение true, то независимо от значения
второго операнда результатом операции
будет величина true. Аналогично в случае
оператора AND, если первый операнд — false, то
значение второго операнда на результат
не влияет — он всегда будет равен false. Если
вы в используете операторы && и ||
вместо обычных форм & и |, то Java не
производит оценку правого операнда
логического выражения, если ответ ясен из
значения левого операнда. Общепринятой
практикой является использование
операторов && и || практически во всех
случаях оценки булевых логических
выражений. Версии этих операторов & и |
применяются только в битовой арифметике.
Тернарный
оператор if-then-else
Общая форма оператора if-then-use
такова:
выражение1? выражение2:
выражениеЗ
В качестве первого операнда —
«выражение1» — может быть использовано
любое выражение, результатом которого
является значение типа boolean. Если
результат равен true, то выполняется
оператор, заданный вторым операндом, то
есть, «выражение2». Если же первый операнд
paвен false, то выполняется третий операнд — «выражениеЗ».
Второй и третий операнды, то есть «выражение2»
и «выражениеЗ», должны возвращать
значения одного типа и не должны иметь тип
void.
В приведенной ниже программе
этот оператор используется для проверки
делителя перед выполнением операции
деления. В случае нулевого делителя
возвращается значение 0.
class Ternary {
public static void
main(String args[]) {
int a = 42;
int b = 2;
int c = 99;
int d = 0;
int e =
(b == 0) ? 0 : (a / b);
int f =
(d == 0) ? 0 : (c / d);
System.out.println("a
= " + a);
System.out.println("b
= " + b);
System.out.println("c
= " + c);
System.out.println("d
= " + d);
System.out.println("a
/ b = " + e);
System.out.println("c
/ d = " + f);
} }
При выполнении этой программы
исключительной ситуации деления на нуль
не возникает и выводятся следующие
результаты:
С:
\>java Ternary
а = 42
b = 2
с = 99
d = 0
a / b = 21
с / d
= 0
Приоритеты
операторов
В Java действует определенный
порядок, или приоритет, операций. В
элементарной алгебре нас учили тому, что у
умножения и деления более высокий
приоритет, чем у сложения и вычитания. В
программировании также приходится
следить и за приоритетами операций. В
таблице указаны в порядке убывания
приоритеты всех операций языка Java.
|
Высший
|
|
( )
|
[ ]
|
.
|
|
|
~
|
!
|
|
|
|
*
|
/
|
%
|
|
|
+
|
-
|
|
|
|
>>
|
>>>
|
<<
|
|
|
>
|
>=
|
<
|
<=
|
|
==
|
!=
|
|
|
|
&
|
|
|
|
|
^
|
|
|
|
|
|
|
|
|
|
|
&&
|
|
|
|
|
| |
|
|
|
|
|
?:
|
|
|
|
|
=
|
op=
|
|
|
|
Низший
|
В первой строке
таблицы приведены три необычных оператора,
о которых мы пока не говорили. Круглые
скобки ()
используются для явной установки
приоритета. Как вы узнали из предыдущей
главы, квадратные скобки []
используются для индексирования
переменной-массива. Оператор . (точка)
используется для выделения элементов из
ссылки на объект. Все же остальные операторы уже
обсуждались в этой главе.
Явные
приоритеты
Поскольку высший приоритет
имеют круглые скобки, вы всегда можете
добавить в выражение несколько пар скобок,
если у вас есть сомнения по поводу
порядка вычислений или вам просто хочется
сделать свои код более читабельным.
а
>> b + 3
Какому из двух выражений,
а
>> (b + 3) или (а
>> b) + 3, соответствует первая строка?
Поскольку у оператора сложения более
высокий приоритет, чем у оператора сдвига,
правильный ответ — а>> (b + а). Так что
если вам требуется выполнить операцию (а>>b)+
3 без скобок не обойтись.
Что
дальше?
Итак, мы рассмотрели все виды
операторов языка Java. Теперь вы можете
сконструировать любое выражение с
различными типами данных.