где ор — арифметический или логический оператор, применяемый вместе с оператором присваивания.
Ниже перечислены укороченные операторы присваивания для арифметических и логических операций.+=-=*=/=%=&=|=^=
Каждый из перечисленных выше операторов состоит из двух знаков, обозначающих арифметическую или логическую операцию, а также операцию присваивания. Поэтому их часто еще называют составными операторами присваивания.
У составных операторов присваивания имеются два главных преимущества. Во-первых, они более компактны, чем их неукороченные эквиваленты. И во-вторых, дают более эффективный исполняемый код, поскольку левый операнд этих операторов вычисляется только один раз. Именно по этим причинам составные операторы присваивания чаще всего применяются в программах, профессионально написанных на Java.Преобразование типов при присваивании
При написании программ очень часто возникает потребность в присваивании значения, хранящегося в переменной одного типа, переменной другого типа. Например, значение int, возможно, потребуется присвоить переменной float, как показано ниже.int i;float f;i = 10;f = i; // присвоить значение переменной типа int переменной типа float
Если типы данных являются совместимыми, значение из правой части оператора присваивания автоматически преобразуется к типу данных в левой его части. Так, в приведенном выше фрагменте кода значение переменной i преобразуется в тип float, а затем присваивается переменной f. Но ведь Java — язык со строгим контролем типов, и далеко не все типы данных в нем совместимы, поэтому неявное преобразование типов выполняется не всегда. В частности, типы boolean и int не являются совместимыми.
Автоматическое преобразование типов в операции присваивания выполняется при соблюдении следующих условий:
оба типа являются совместимыми;
целевой тип обладает более широким диапазоном допустимых значений, чем исходный тип.
Если оба перечисленных выше условия соблюдаются, происходит расширяющее преобразование типов. Например, диапазона значений, допустимых для типа int, совершенно достаточно, чтобы представить любое значение типа byte, а кроме того, оба эти типа данных являются целочисленными. Поэтому и происходит автоматическое преобразование типа byte в тип int.
С точки зрения расширяющего преобразования типов целочисленные типы и типы с плавающей точкой совместимы друг с другом. Например, приведенная ниже программа написана корректно, поскольку преобразование типа long в тип double является расширяющим и выполняется автоматически.// Демонстрация автоматического преобразования типа long в тип double,class LtoD { public static void main(String args[]) { long L; double D; L = 100123285L; // Автоматическое преобразование типа long в тип double. D = L; System.out.println("L and D: " + L + " " + D); }}
В то же время тип double не может быть автоматически преобразован в тип long, поскольку такое преобразование уже не является расширяющим. Следовательно, приведенный ниже вариант той же самом программы оказывается некорректным.// *** Эта программа не подлежит компиляции. ***class LtoD { public static void main(String args[]) { long L; double D; D = 100123285.0; // Тип double не преобразуется автоматически в тип long. L = D; // Ошибка!!! System.out.println("L and D: " + L + " " + D) ; }}
Автоматическое преобразование числовых типов в тип char или boolean не производится. Кроме того, типы char и boolean несовместимы друг с другом. Тем не менее переменной char может быть присвоено значение, представленное целочисленным литералом.Приведение несовместимых типов
Несмотря на всю полезность неявных автоматических преобразований типов, они неспособны удовлетворить все потребности в программировании, поскольку допускают лишь расширяющие преобразования совместимых типов. А во всех остальных случаях приходится обращаться к приведению типов. Приведение — это команда компилятору преобразовать результат вычисления выражения в указанный тип. А для этого требуется явное преобразование типов. Ниже показана общая форма приведения типов.(целевой_тип) выражение
где целевой_тип обозначает тот тип, в который желательно преобразовать указанное выражение. Так, если требуется привести значение, возвращаемое выражением х / у, к типу int, это можно сделать следующим образом:double х, у;// ...(int) (х / у)
В данном случае приведение типов обеспечит преобразование результатов выполнения выражения в тип int, несмотря на то, что переменные х и у принадлежат к типу double. Выражение х / у следует непременно заключить в круглые скобки, иначе будет преобразован не результат деления, а только значение переменной х. Приведение типов в данном случае требуется потому, что автоматическое преобразование типа double в тип int не выполняется.
Если приведение типов приводит к сужающему преобразованию, то часть информации может быть потеряна. Например, в результате приведения типа long к типу int часть информации потеряется, если значение типа long окажется больше диапазона представления чисел для типа int, поскольку старшие разряды этого числового значения отбрасываются. Когда же значение с плавающей точкой приводится к целочисленному, в результате усечения теряется дробная часть этого числового значения. Так, если присвоить значение 1,23 целочисленной переменной, то в результате в ней останется лишь целая часть исходного числа (1), а дробная его часть (0,23) будет потеряна.
Ниже приведен пример программы, демонстрирующий некоторые виды преобразований, требующие явного приведения типов.// Демонстрация приведения типов,class CastDemo { public static void main(String args[]) { double x, y; byte b; int i; char ch; x = 10.0; У = 3.0; // В данном случае теряется дробная часть числа. i = (int) (х / у); // привести тип double к типу int System.out.println("Integer outcome of x / y: " + i) ; i = 100; // А в этом случае данные не теряются. Тип byte может // содержать значение 100. Ъ = (byte) i; System.out.println ("Value of b: " + b) ; i = 257; //На этот раз данные теряются. Тип byte не может // содержать значение 257. b = (byte) i; System.out.println("Value of b: " + b); b = 88; // Представление символа X в коде ASCII. //И снова требуется явное приведение несовместимых типов. ch = (char) b; System.out.println("ch: " + ch); }}
Выполнение этой программы дает следующий результат:Integer outcome of х / у: 3Value of b: 100Value of b: 1ch: X
В данной программе приведение выражения (х / у) к типу int означает потерю дробной части числового значения результата деления. Когда переменной b присваивается значение 100 из переменной i, данные не теряются, поскольку диапазон допустимых значений у типа byte достаточен для представления этого значения. Далее при попытке присвоить переменной b значение 257 снова происходит потеря данных, поскольку значение 257 оказывается за пределами диапазона допустимых значений для типа byte. И наконец, когда переменной char присваивается содержимое переменной типа byte, данные не теряются, но явное приведение типов все же требуется.Предшествование операторов
В табл. 2.3 приведен порядок предшествования всех операторов в Java: от самого высокого до самого низкого. В эту таблицу включен ряд операторов, рассматриваемых далее в этой книге. Формально разделители [], () и . могут действовать как операторы, и в этом случае они будут иметь наивысший порядок предшествования.
Таблица 2.3. Предшествование операторов в JavaНаивысший порядок++ (постфиксный)-- (постфиксный)++ (префиксный)-- (префиксный)~!+ (унарный плюс)- (унарный минус)(приведение типов)*/%+->><<<<<>>=<<=instanceof==!=&^|&&||?:=op=
Пример для опробования 2.2.Отображение таблицы истинности для логических операторов
В этом проекте предстоит создать программу, которая отображает таблицу истинности для логических операторов Java. Для удобства восприятия отображаемой информации следует выровнять столбцы таблицы. В данном проекте используется ряд языковых средств, рассмотренных ранее в этой главе, включая управляющие последовательности и логические операторы, а также демонстрируются отличия в предшествовании арифметических и логических операторов.