Чтобы понять, как работают операторы Java, нужно хорошо представлять, как устроен этот язык программирования. Любой код на Java состоит из инструкций и выражений. По сути, и то и другое — просто фрагменты кода. Разница между ними в том, за что они отвечают.
Инструкции ― каркас программы, к ним относят условные конструкции, циклы и классы. Например, if, if-else, while, for. Они задают маршрут, по которому компьютер будет обрабатывать код, но сами никаких действий не производят и не возвращают результат. За эту часть в Java отвечают выражения. С их помощью программисты работают с данными и проводят вычисления.
Выражения в Java состоят из операндов и операторов. Операторы — это команды, которые указывают компьютеру, какие действия нужно совершить над операндами. Например, в выражении 1 + 2 оба числа будут операндами, а знак сложения — оператором. Операторы языка Java позволяют выстраивать выражения любой сложности, на основе которых компьютер выполнит вычисления и вернёт значение.
В Java операторы делятся на пять основных групп:
● Операторы присваивания
● Арифметические операторы
● Операторы сравнения
● Логические операторы
● Побитовые операторы
Есть и другие операторы, которые решают свои специфические задачи. Например, с помощью укороченных операторов программисты комбинируют разные типы операторов Java, чтобы компьютер быстрее обрабатывал код и его было проще читать.
Чтобы написать код, который будет корректно работать, новичку нужно понимать, какие есть типы операторов Java и что они делают. На курсе «Java-разработчик» студенты изучают самые используемые группы операторов и практикуются работать с ними в тренажёре.
Выглядит он как знак равенства. Например, в выражении x = 1 переменной x присвоилось значение 1. И в любых выражениях, где присутствует x, компьютер будет подставлять на его место единицу, пока разработчик не перепишет значение этой переменной.
С помощью оператора присваивания можно записать в переменную результат вычисления. Например, x = 1 + 2. Теперь компьютер присвоит переменной x значение 3.
В переменную можно даже записать результат другого присваивания. Например, х = у = 1. В переменную x запишется результат выражения y = 1. Если y изменится, вслед за ним изменится и x. Здесь важно помнить, что в Java данные перетекают справа налево.
Минус в Java тоже имеет двойной смысл: когда этот оператор применяют к двум операндам, минус называют бинарным. В этом случае речь идёт о вычитании. Например, 10 - 3 = 7. Когда же минус относится только к одному операнду, его называют унарным — он указывает, что значение операнда будет отрицательным: x = -1.
Большую часть математических операций в Java разработчики выполняют с помощью библиотек. Они содержат готовые функции для вычисления синусов, косинусов, возведения в степень и более сложных арифметических действий.
Операторы сравнения очень точные ― они сравнивают не только сами данные, но и их тип. Из очевидного: нельзя сравнить строку с числом. Программа выдаст ошибку, потому что это объекты разного типа.
Есть тонкости, которые новичкам нужно учитывать. Например, в Java есть тип данных int — целое число, а есть класс Integer, куда входит тип int. При попытке сравнить объект типа int с int результат будет верный, а вот при сравнении двух объектов типа Integer компьютер выдаст ошибку, поскольку для машины это разные объекты. Тот же результат получится, если сравнивать между собой строки. Для объектов типа String, Integer и аналогичных оператор сравнения не применяют.
Логическое НЕ выполняет роль отрицания и придаёт операнду или выражению, перед которым стоит, обратное значение.
Чтобы представить, как работают два других оператора, можно провести параллель с математикой. Такая аналогия поможет быстрее запомнить, в чём разница.
Логическое ИЛИ ещё называют логическим сложением — этот оператор работает так же, как плюс в математике. Только в двоичной системе, где true — это 1, false — это 0, а 1 + 1 = 1, потому что двойки в этой системе попросту не существует.
1 + 0 = 1
0 + 1 = 1
1 + 1 = 1
0 + 0 = 0
Логическое И можно представить как умножение в двоичной системе.
1 * 0 = 0
0 * 1 = 0
0 * 0 = 0
1 * 1 = 1
Логические операторы Java позволяют компьютеру не проверять всё выражение, если результат очевиден по первому операнду. Так код выполняется быстрее.
Любое число в Java можно представить в виде цепочки битов, состоящей из нулей и единиц. Старший бит в цепочке, который стоит первым слева, всегда указывает на знак числа: положительное — 0, отрицательное — 1. Нули в начале цепочки обычно опускают для простоты восприятия. Например, число 5 в двоичной системе счисления обычно записывают как 101, хотя на самом деле оно выглядит как 00000101.
Поскольку компьютер видит только единицы и нули, всю входящую информацию он сначала преобразует в понятную ему форму и только потом выполняет вычисления. Чтобы код обрабатывался быстрее, можно сразу обращаться к компьютеру на его языке. Побитовые операторы Java позволяют работать с двоичным представлением любого числа и выполнять операции без перевода, поэтому они очень быстрые. Обычно их используют для работы со сложными данными: картинками, видео или музыкой, например, чтобы сделать фотографию чёрно-белой или увеличить громкость музыки.
Побитовые операторы работают по битам — проходятся по всей цепочке, перебирая значения одно за другим. Разберёмся, как именно они это делают.
Побитовое НЕ — это унарный оператор отрицания. Он применяется только к одной цепочке битов, проходится по каждому её элементу и меняет значение на противоположное. Например, ∼101 = 010. Но это не то же самое, что поставить перед числом знак минус. Побитовое НЕ не делает число отрицательным.
Побитовое И — это бинарный оператор, который применяется к двум цепочкам битов. Сначала он обращается к первому биту в каждой из цепочек, потом ко второму и так далее. А результатом этого выражения будет третья цепочка.
Работает этот оператор по тому же принципу, что и логическое И. Его ещё называют побитовым умножением. Только в том случае, когда в обеих цепочках стоит единица, программа вернёт единицу. Во всех остальных случаях результатом будет ноль.
111 & 000 = 0
111 & 001 = 001
111 & 010 = 010
Побитовое ИЛИ называют побитовым сложением. Этот оператор делает то же самое, что и логическое ИЛИ, только применяется не к отдельным величинам, а к цепочкам битов. Если хоть в одной из цепочек есть единица, оператор вернёт единицу.
101 || 010 = 111
011 || 100 = 111
010 || 100 = 110
Исключающее побитовое ИЛИ принято обозначать формулой «либо то, либо то». Если в обеих цепочках стоят единицы, программа вернёт ноль. Если в обеих цепочках стоят нули, она тоже вернёт ноль. И только когда в одной цепочке стоит ноль, а в другой единица, программа вернёт единицу.
110 ^ 101 = 011
101 ^ 010 = 111
100 ^ 111 = 011
Сдвиг вправо выполняется по формуле x >> y, где x — цепочка битов, а y — количество шагов, на которое её нужно сдвинуть.
Разберём принцип действия этого оператора на примере: 101 >> 1 = 010.
Если проводить параллель с математикой, то при каждом сдвиге цепочки битов на один шаг вправо выполняется целочисленное деление исходного числа на два. Для наглядности переведём операнды в десятичную систему счисления. Двоичной записи 101 соответствует число 5. Оператор делит его на два, отбрасывает остаток и возвращает число 2, которому в двоичной системе счисления соответствует 010. Всё сходится!
Сдвиг вправо с заполнением нулями отличается от предыдущего оператора лишь тем, что все освободившиеся ячейки слева он всегда заполняет нулями. Если до выполнения операции старшим битом была единица, на её место встанет ноль, знак числа изменится и из отрицательного оно превратится в положительное.
Сдвиг влево выполняется по тому же принципу, что и сдвиг вправо, только в обратную сторону. Чтобы посмотреть, как это работает, сдвинем операнд из примера выше влево: 101 << 1 = 1010.
Сдвиг того же числа на два шага влево вернёт результат — 10100. В десятичной системе счисления ему соответствует число 20. Всё выражение можно было бы записать в две итерации: 5 * 2 = 10 и 10 * 2 = 20.
На первых порах с побитовыми операторами Java лучше обращаться предельно внимательно:
● Они меняют знак числа, превращая отрицательное в положительное.
● При переводе результатов вычисления из двоичной системы в десятичную результат может получиться неочевидным.
Тернарный оператор или оператор условия Java
Условных операторов в Java нет. Конструкции if и if-else, которые в других языках программирования называют условными операторами, в Java относятся к инструкциям.
Но иногда программистам хочется добавить в выражение условие. Специально для этого они придумали тернарный оператор — ?:, который можно считать аналогом инструкции if.
Например, в выражении a ? 10 : 11 задано условие: если а — true, программа вернёт 10, если false — 11. То есть всё будет зависеть от значения переменной а, ей можно присвоить любое числовое значение и даже целое выражение. Например, a = 1==2. В этом случае тернарный оператор вернёт 11— единица не равна двойке, а значит, а — false.
Этот оператор популярен среди опытных разработчиков, но новичкам лучше его не использовать, чтобы не запутаться.
Оператор instanceof
Это простой оператор, который позволяет проверить тип входящей переменной и возвращает булевое значение — true или false. Например, с помощью выражения x instanceof Integer программист задаёт компьютеру вопрос: эта переменная относится к классу Integer — да или нет? Оператор полезен, когда значение x программа получает извне.
Укороченные операторы
Для упрощения кода разработчики придумали использовать укороченные операторы Java. Они позволяют провести вычисление и присвоить его результат переменной всего одной командой. Например, выражение a = a + 2 можно записать короче: a += 2. Означать эти выражения будут одно и то же. Подобный фокус можно проделать с любыми побитовыми и логическими операторами Java, используя общую формулу.
Инкремент и декремент
Иногда эти операторы в Java относят к арифметическим, но правильнее рассматривать их отдельно.
Декремент и инкремент бывают префиксными — стоят перед переменной, а бывают постфиксными — после переменной. Для самой переменной разницы нет никакой: ++a и a++ увеличивают её на единицу. Однако выражения b = ++a и b = a++ будут отличаться по смыслу. В первом случае b присвоится значение ++a, а во втором — только a. Сама переменная a увеличится на единицу уже после того, как её значение будет присвоено b. Поэтому новичкам рекомендуют вместо инкремента и декремента использовать аналоги. Например, заменить a++ на a += 1 или даже на a = a + 1.
В языке Java последовательность выполнения операций выстроена так, чтобы соблюсти правила арифметики. Сложение идёт после умножения, умножение в одну цепочку выполняется строго слева направо, а выражение, взятое в круглые скобки, имеет наивысший приоритет. Рассмотрим приоритетность выполнения операторов Java в таблице.
Пётр Кушнир
Чтобы до конца понять суть операторов Java, придётся параллельно разбираться с типами данных и двоичной арифметикой. Всё это поможет понять, как устроены вычисления выражений с операторами «под капотом». Благодаря этому разработчик научится писать корректный код и понимать, что написали другие.
Читать также: