х = а * -Ь;
но читающий код может запутаться, так что яснее будет написать так:
х = а * (-Ь):
Унарный минус меняет знак числа на противоположный. Унарный плюс су¬ществует «для симметрии», хотя и не производит никаких действий.
Автоувеличение и автоуменьшение
В Java, как и в С, существует множество различных сокращений. Сокращения могут упростить написание кода, а также упростить или усложнить его чтение.
Два наиболее полезных сокращения — это операторы увеличения (инкре¬мента) и уменьшения (декремента) (также часто называемые операторами ав¬томатического приращения и уменьшения). Оператор декремента записывается в виде — и означает «уменьшить на единицу». Оператор инкремента обознача¬ется символами ++ и позволяет «увеличить на единицу». Например, если пере¬менная а является целым числом, то выражение ++а будет эквивалентно (а = а + 1). Операторы инкремента и декремента не только изменяют перемен¬ную, но и устанавливают ей в качестве результата новое значение.
Каждый из этих операторов существует в двух версиях — префиксной и постфиксной. Префиксный инкремент значит, что оператор ++ записывается перед переменной или выражением, а при постфиксном инкременте оператор следует после переменной или выражения. Аналогично, при префиксном дек¬ременте оператор — указывается перед переменной или выражением, а при
постфиксном — после переменной или выражения. Для префиксного инкре¬мента и декремента (то есть ++а и —а) сначала выполняется операция, а затем выдается результат. Для постфиксной записи (а++ и а—) сначала выдается зна¬чение, и лишь затем выполняется операция. Например:
// operators/AutoInc java
import static net mindview util Print *.
public class Autolnc {
i); + ++i) + i++) i). + --i) + i-) i),
// Префиксный инкремент
// Постфиксный инкремент
// Префиксный декремент
// Постфиксный декремент
public static void main(String[] args) { int i = 1; printC'i : print("++i print("i++ printC'i • print C'--i printC'i-- printC'i
} /* Output- i . 1 ++i • 2 i++ . 2 i . 3 -i . 2 1-- 2
i • 1 *///.-
Вы видите, что при использовании префиксной формы результат получает¬ся после выполнения операции, тогда как с постфиксной формой он доступен до выполнения операции. Это единственные операторы (кроме операторов при¬сваивания), которые имеют побочный эффект. (Иначе говоря, они изменяют свой операнд вместо простого использования его значения.)
Оператор инкремента объясняет происхождение названия языка С++; под¬разумевается «шаг вперед по сравнению с С». В одной из первых речей, посвя¬щенных Java, Билл Джой (один из его создателей) сказал, что «Java=C++—» («Си плюс плюс минус минус»). Он имел в виду, что Java — это С++, из кото¬рого убрано все, что затрудняет программирование, и поэтому язык стал гораз¬до проще. Продвигаясь вперед, вы увидите, что отдельные аспекты языка, ко¬нечно, проще, и все же Java не настолько проще С++.
Операторы сравнения
Операторы сравнения выдают логический (boolean) результат. Они проверяют, в каком отношении находятся значения их операндов. Если условие проверки истинно, оператор выдает true, а если ложно — false. К операторам сравнения относятся следующие: «меньше чем» (<), «больше чем» (>), «меньше чем или равно» (<=), «больше чем или равно» (>=), «равно» (==) и «не равно» (!=). «Рав¬но» и «не равно» работают для всех примитивных типов данных, однако ос¬тальные сравнения не применимы к типу boolean.
Проверка объектов на равенство
Операции отношений == и != также работают с любыми объектами, но их смысл нередко сбивает с толку начинающих программистов на Java. Пример:
//: operators/AutoInc.java
public class Equivalence {
public static void main(String[] args) { Integer nl = new Integer(47); Integer n2 = new Integer(47); System.out.println(nl == n2); System out println(nl != n2);
}
} /* Output.
false
true
*///:-
Выражение System.out.println(nl == n2) выведет результат логического срав¬нения, содержащегося в скобках. Казалось бы, в первом случае результат дол¬жен быть истинным (true), а во втором — ложным (false), так как оба объекта типа Integer имеют одинаковые значения. Но в то время как содержимое объек¬тов одинаково, ссылки на них разные, а операторы != и == сравнивают именно ссылки. Поэтому результатом первого выражения будет false, а второго — true. Естественно, такие результаты поначалу ошеломляют.
А если понадобится сравнить действительное содержимое объектов? При¬дется использовать специальный метод equals(), поддерживаемый всеми объек¬тами (но не примитивами, для которых более чем достаточно операторов == и !=). Вот как это делается:
//: operators/EqualsMethod.java
public class EqualsMethod {
public static void main(String[] args) { Integer nl = new Integer(47); Integer n2 = new Integer(47); System.out.println(nl.equal s(n2));
}
} /* Output:
true
*///:-
На этот раз результат окажется «истиной» (true), как и предполагалось. Но все не так просто, как кажется. Если вы создадите свой собственный класс вроде такого:
//: operators/EqualsMethod2 java
// Метод equals() по умолчанию не сравнивает содержимое
class Value { int i;
}
public class EqualsMethod2 {
public static void main(String[] args) {
Value vl = new ValueO.
Value v2 = new ValueO.
vl.i = v2 i = 100;
System out println(vl equals(v2));
}
} /* Output false *///.-
мы вернемся к тому, с чего начали: результатом будет false. Дело в том, что ме¬тод equals() по умолчанию сравнивает ссылки. Следовательно, пока вы не пере¬определите этот метод в вашем новом классе, не получите желаемого результа¬та. К сожалению, переопределение будет рассматриваться только в главе 8, а пока осторожность и общее понимание принципа работы equals() позволит из¬бежать некоторых неприятностей.
Большинство классов библиотек Java реализуют метод equals() по-своему, сравнивая содержимое объектов, а не ссылки на них.
Логические операторы
Логические операторы И (&&), ИЛИ (||) и НЕ (!) производят логические значе¬ния true и false, основанные на логических отношениях своих аргументов. В следующем примере используются как операторы сравнения, так логические операторы:
//: operators/Bool Java
// Операторы сравнений и логические операторы.
import java.util.*;
import static net.mindview.util.Print.*;
public class Bool {
public static void main(String[] args) { Random rand = new Random(47); int i = rand.nextlnt(lOO): int j = rand.nextlnt(lOO); printC'i = " + i); printC'j = " + J): printC'i > j is " + (i > j)); printC'i < j is " + (i < j)); printC'i >= j is " + (i >= j)); printC'i <= j is " + (i <= j)); printC'i == j is " + (i == j)); printC'i != j is " + (i != j)); // В Java целое число (int) не может // интерпретироваться как логический тип (boolean) //! printC'i && j is " + (i && j)); //! printC'i || j is " + (i || j)); //! printC!i is " + !i); printed < 10) && (j < 10) is "
+ (d < 10) && (j < 10)) ); printed < 10) || (j < 10) is "
+ (d < 10) || (J < 10)) );
}
} /* Output: i = 58
J = 55
i > j is true i < j is false i >= j is true i <= j is false i == j is false i != j is true
(i < 10) && (j < 10) is false (i <10) || (j « 10) is false */// ~
Операции И, ИЛИ и НЕ применяются только к логическим (boolean) значе¬ниям. Нельзя использовать в логических выражениях не-Ьоо1еап-типы в качест¬ве булевых, как это разрешается в С и С++. Неудачные попытки такого рода видны в строках, помеченных особым комментарием //! (этот синтаксис позво¬ляет автоматически удалять комментарии для удобства тестирования). После¬дующие выражения вырабатывают логические результаты, используя операто¬ры сравнений, после чего к полученным значениям примененяются логические операции.