Философия Java3
Шрифт:
В последней команде программы полученное значение не приводится обратно к Ь, поэтому получается верное действие.
Следующий пример демонстрирует использование всех операторов, так или иначе связанных с поразрядными операциями:
//; operators/BitManipulation.java // Использование поразрядных операторов, import java.util.*;
import static net.mindview.util Print.*;
public class BitManipulation {
public static void main(String[] args) { Random rand = new Random(47);
int i = rand nextlntO, int j = rand.nextlntO. printBinarylntC'-l", -1); printBinarylntC'+l", +1); int maxpos = 2147483647; printBinaryInt("макс положит.", maxpos); int maxneg = -2147483648; printBinarylntC'MaKc отрицат.". maxneg); printBinarylntC'i". i); printBinaryInt("~i", ~i); printBinaryInt("-i", -i); printBinarylntC'j", j), printBinarylntC'i & j". i & j), printBinarylntC'i | j", i | j); printBinarylntC'i A j". i A j); printBinarylntC'i « 5", i «5); printBinarylntC'i » 5", i » 5): printBinarylntC'M) » 5", (~i) » 5); printBinarylntC'i »> 5", i »> 5); printBinarylntC'M) »> 5", (~i) »> 5);
long 1 = rand.nextLongO; long m = rand.nextLongO; printBinaryLong("-lL", -1L); printBinaryLong("+lL", +1L): long 11 = 9223372036854775807L, printBinaryLongC'MaKC. положит.", 11); long 1 In = -9223372036854775808L; printBinaryLongC'MaKC. отрицат ", lln); printBinaryLongC'l", 1); printBinaryLong("~l", -1), printBinaryLong("-l", -1), printBi naryLongC'm", m), printBinaryLongC'l & m", 1 & m); printBinaryLongC'l | m", 1 | m); printBinaryLongC'l A m", 1 A m); printBinaryLongC'l « 5", 1 «5); printBinaryLongC'l » 5". 1 » 5); printBinaryLong("(~l) » 5", (~1) » 5). printBinaryLongC'l »> 5". 1 »> 5); printBi naryLongC'H) »> 5", (~1) »> 5); moni tor.expect("Bi tMani pulati on.out");
}
static void printBinaryInt(String s, int i) {
print(s + ". int: " + i + двоичное: \n " + Integer toBinaryString(i));
}
static void printBinaryLong(String s, long 1) {
print(s + \ long: " + 1 + ", двоичное:\п " + Long.toBinaryStringd));
}
} /* Output-
– 1, int- -1, двоичное.
11111111111111111111111111111111 +1, int. 1, двоичное. 1
макс, положит . int- 2147483647. двоичное: 1111111111111111111111111111111
макс, отрицат., int: -2147483648, двоичное-10000000000000000000000000000000 i, int- -1172028779. двоичное: 10111010001001000100001010010101 ~i, int. 1172028778, двоичное. 1000101110110111011110101101010 -i, int. 1172028779. двоичное: 1000101110110111011110101101011 j. int: 1717241110, двоичное: 1100110010110110000010100010110 i & j, int- 570425364, двоичное: 100010000000000000000000010100 i | j, int.
– 25213033, двоичное. 11111110011111110100011110010111 i A j. int: -595638397, двоичное. 11011100011111110100011110000011 i «5, int: 1149784736, двоичное-1000100100010000101001010100000 i » 5, int -36625900, двоичное. 11111101110100010010001000010100 (~i) » 5, int 36625899, двоичное. 10001011101101110111101011 i »> 5, int. 97591828, двоичное. 101110100010010001000010100 (~i) »> 5, int- 36625899, двоичное. 10001011101101110111101011
*///.-
Два метода в конце, printBinaryInt и printBinaryl_ong, получают в качестве параметров, соответственно, числа int и long и выводят их в двоичном формате вместе с сопроводительным текстом. Вместе с демонстрацией поразрядных операций для типов int и long этот пример также выводит минимальное и максимальное значение, +1 и -1 для этих типов, чтобы вы лучше понимали, как они выглядят в двоичном представлении. Заметьте, что старший бит обозначает знак: 0 соответствует положительному и 1 — отрицательному числам. Результат работы для типа int приведен в конце листинга
Тернарный оператор «если-иначе»
Тернарный оператор необычен тем, что он использует три операнда. И все же это действительно оператор, так как он производит значение, в отличие от обычной конструкции выбора if-else, описанной в следующем разделе. Выражение записывается в такой форме:
логическое-условие ? выражениеО : выражение1
Если логическое-условие истинно (true), то затем вычисляется выражениеО, и именно его результат становится результатом выполнения всего оператора. Если же логическое-условие ложно (false), то вычисляется выражение1, и его значение становится результатом работы оператора.
Конечно, здесь можно было бы использовать стандартную конструкцию if-else (описываемую чуть позже), но тернарный оператор гораздо компактнее. Хотя С (где этот оператор впервые появился) претендует на звание лаконичного языка, и тернарный оператор вводился отчасти для достижения этой цели, будьте благоразумны и не используйте его всюду и постоянно — он может ухудшить читаемость программы.
Операторы + и += для String
В Java существует особый случай использования оператора: операторы + и += могут применяться для конкатенации (объединения) строк, и вы уже это видели. Такое действие для этих операторов выглядит вполне естественно, хотя оно и не соответствует традиционным принципам их использования.
При создании С++ в язык была добавлена возможность перегрузки операторов, позволяющей программистам С++ изменять и расширять смысл почти любого оператора. К сожалению, перегрузка операторов, в сочетании с некоторыми ограничениями С++, создала немало проблем при проектировании классов. Хотя реализацию перегрузки операторов в Java можно было осуществить проще, чем в С++ (это доказывает язык С#, где существует простой механиз перегрузки), эту возможность все же посчитали излишне сложной, и поэтому программистам на Java не дано реализовать свои собственные перегруженные операторы, как это делают программисты на С++.
Использование + и += для строк (String) имеет интересные особенности. Если выражение начинается строкой, то все последующие операнды также должны быть строками (помните, что компилятор превращает символы в кавычках в объект String).
int х = 0. у = 1. z = 2;
String s = "х. у, z
System.out.println(s + x + у + z),
В данном случае компилятор Java приводит переменные х, у и z к их строковому представлению, вместо того чтобы сначала арифметически сложить их. А если вы запишете
System.out.println(x + s); то и здесь Java преобразует х в строку.
Типичные ошибки при использовании операторов
Многие программисты склонны второпях записывать выражение без скобок, даже когда они не уверены в последовательности вычисления выражения. Это верно и для Java.
Еще одна распространенная ошибка в С и С++ выглядит следующим образом:
while(x = у) { // .
}
Программист хотел выполнить сравнение (==), а не присвоение. В С и С++ результат этого выражения всегда будет истинным, если только у не окажется нулем; вероятно, возникнет бесконечный цикл. В языке Java результат такого выражения не будет являться логическим типом (boolean), а компилятор ожидает в этом выражении именно boolean и не разрешает использовать целочисленный тип int, поэтому вовремя сообщит вам об ошибке времени компиляции, упредив проблему еще перед запуском программы. Поэтому подобная ошибка в Java никогда не происходит. (Программа откомпилируется только в одном случае: если х и у одновременно являются типами boolean, и тогда выражение х = у будет допустимо, что может привести к ошибке.)