Поиск по сайту:

Как использовать операторы в Java


Автор выбрал программу Write for DOnations.

Введение

Оператор — это комбинация одного или нескольких символов, например, хорошо известные арифметические операторы минус (-) и плюс (+) или более продвинутый instanceof. Когда вы применяете операторы к значениям или переменным, вы получаете результат операции. Такие операции являются фундаментальными в программировании, потому что их результат присваивается переменной или оценивается далее, пока не будет достигнута конечная цель программы.

Для этого руководства вы должны быть знакомы с операндом, то есть значением или переменной, к которой применяются операторы. В зависимости от количества операндов операторы можно разделить на три группы. Во-первых, когда в операции есть только один операнд, операторы называются унарными. Точно так же бинарные операторы включают два операнда. Наконец, когда есть три операнда, оператор является троичным. В соответствии с этой классификацией данное руководство состоит из трех основных частей для каждого типа оператора.

В этом руководстве вы будете использовать все три типа операторов для управления примитивными типами данных, например, в математических уравнениях. Вы также будете использовать операторы в более сложных сценариях со ссылочными типами и изучите некоторые правила приоритета операторов.

Предпосылки

Чтобы следовать этому руководству, вам понадобятся:

  • Среда, в которой вы можете выполнять программы Java, чтобы следовать примерам. Чтобы настроить это на вашем локальном компьютере, вам потребуется следующее:
    • На вашем компьютере установлена Java (версия 11 или выше) с компилятором, входящим в комплект Java Development Kit (JDK). Для Ubuntu и Debian следуйте инструкциям по загрузке для установки Java.
    • Для компиляции и запуска примеров кода в этом руководстве используется руководство Introduction to JShell.

    Знакомство с Java и объектно-ориентированным программированием, которое вы можете найти в нашем руководстве «Как написать свою первую программу на Java».

    Понимание типов данных Java, которое обсуждается в нашем руководстве «Понимание типов данных в Java».

    Унарные операторы

    Унарные операторы применяются к одному операнду, что делает их наиболее простыми. Часто используются унарные операторы, потому что они делают ваш код более кратким и читабельным. Они заменяют необходимость явного описания таких операций, как увеличение и уменьшение значений. Однако в сочетании с другими операторами унарные операторы также могут быть сложными в использовании, как вы узнаете позже в этом разделе.

    Далее вы будете использовать унарные операторы для увеличения и уменьшения значений, а также инвертировать логические значения.

    Операторы увеличения и уменьшения

    Операторы Increment и decrement, как следует из их названий, увеличивают и уменьшают числа. Оператор приращения — это комбинация двух знаков плюс (++), а оператор уменьшения — два знака минус (--). Эти операторы используются до и после операндов.

    Преинкрементация и преддекрементация

    Когда вы используете операторы перед операндом, вы выполняете предварительное увеличение или предварительное уменьшение в зависимости от того, используете ли вы ++ или --. Когда вы используете операторы pre, вы изменяете значение операнда перед его использованием. Таким образом, когда вы фактически используете значение, оно уже изменено.

    Информация: Чтобы следовать примеру кода в этом руководстве, откройте инструмент Java Shell в вашей локальной системе, выполнив команду jshell. Затем вы можете копировать, вставлять или редактировать примеры, добавляя их после приглашения jshell> и нажимая ENTER. Чтобы выйти из jshell, введите /exit.

    Чтобы использовать оператор предварительного увеличения, введите в jshell следующее:

    1. int theAnswer = 42;
    2. System.out.println("Preincrementing: " + ++theAnswer);

    В первой строке вы определяете переменную theAnswer со значением 42. Во второй строке вы используете метод println(), чтобы напечатать его и таким образом продемонстрировать, как он изменился.

    Оператор преинкремента в приведенном выше примере — это ++, и он помещается перед theAnswer. Таким образом, используя оператор предварительного приращения, вы сначала увеличиваете значение theAnswer до 43. После этого, когда println() его обрабатывает, он уже равен 43, и поэтому вы видите напечатанное:

    Output
    theAnswer ==> 42 Preincrementing: 43

    Предварительное уменьшение работает аналогично, но вместо увеличения вы уменьшаете значение операнда. В качестве упражнения измените приведенный выше пример так, чтобы вместо оператора преинкремента ++ использовался оператор предекремента --.

    Постинкремент и постдекремент

    В отличие от операторов pre, операторы post изменяют значение операнда после его использования. В некоторых конкретных случаях обычно используются операторы post или pre, но в целом это вопрос личных предпочтений.

    Чтобы продемонстрировать, как работают операторы post, вы постинкрементируете значение theAnswer и изучаете, как изменяется его значение. Добавьте следующие строки в jshell:

    1. int theAnswer = 42;
    2. System.out.println("Postincrementing: " + theAnswer++);
    3. System.out.println("Final value: " + theAnswer);

    Переменная theAnswer сначала равна 42. Затем он печатается и постинкрементируется. В последней строке вы печатаете его снова, чтобы увидеть его окончательное значение.

    Ваш вывод должен быть:

    Output
    theAnswer ==> 42 Postincrementing: 42 Final value: 43

    Как видите, theAnswer остается 42 во время постинкремента. Когда вы печатаете его снова после постинкремента, он равен 43 (Окончательное значение: 43).

    Постдекрементация работает так же. Значение сначала извлекается и используется, и только после этого оно уменьшается. В качестве упражнения попробуйте заменить оператор постинкремента ++ оператором постдекремента -- или даже включить один из операторов pre.

    Оператор НЕ

    Оператор НЕ, также известный как оператор логического дополнения, инвертирует значение логического операнда. Он представлен восклицательным знаком !. Обычно вы используете оператор NOT, когда у вас есть логическая переменная или значение, и вы хотите повторно использовать его с противоположным значением. Таким образом, вам не нужно без необходимости создавать другую переменную с противоположным значением.

    Вот пример того, как работает оператор NOT. Для простоты вы измените значение true:

    1. boolean isJavaFun = !true;
    2. System.out.println(isJavaFun);

    Вы определяете логическую переменную isJavaFun как true. Однако оператор NOT предшествует true; таким образом, значение true меняется на false. Когда вы запустите приведенный выше код, будет напечатан следующий вывод:

    Output
    isJavaFun ==> false false

    Вот как работает оператор NOT. Иногда это может сбивать с толку и трудно заметить, поэтому вы должны использовать его экономно.

    В приведенном выше случае вместо !true вы могли бы использовать false. Это правильный подход, потому что он чище и интуитивно понятнее. Как правило, рекомендуется использовать литерал или метод напрямую, а не альтернативы, требующие дополнительных операций. Однако в некоторых случаях это не всегда имеет смысл или даже возможно. Например, часто используется оператор NOT для инвертирования результата логического метода.

    Например, чтобы проверить, содержит ли строка другую строку, вы можете использовать метод contains(). Однако, если вы хотите проверить обратное (то есть, когда строка не содержит другой строки), альтернативного встроенного метода нет. Вам нужно будет использовать contains() с оператором NOT.

    Представьте, что у вас есть строка Java is smart., и вы хотите проверить:

    1. Строка содержит smart.
    2. Строка не содержит hard.

    Чтобы проверить это, вы будете использовать следующий код:

    1. String javaIsSmart = "Java is smart.";
    2. boolean isSmartPartOfJava = javaIsSmart.contains("smart");
    3. boolean isHardNotPartOfJava = !javaIsSmart.contains("hard");

    В первой строке вы определяете переменную String javaIsSmart. Во второй строке вы определяете логическую переменную isSmartPartOfJava как результат операции из метода contains() — в данном случае, является ли строка smart является частью строки javaIsSmart. Точно так же в третьей строке вы определяете логическую переменную isHardNotPartOfJava, которая определяется тем, находится ли hard не в javaIsSmart.

    Когда вы запустите этот код в jshell, вы получите следующий вывод:

    Output
    javaIsSmart ==> "Java is smart." isSmartPartOfJava ==> true isHardNotPartOfJava ==> true

    Согласно приведенному выше выводу:

    • isSmartPartOfJava имеет значение true, поскольку smart находится в javaIsSmart.
    • isHardNotPartOfJava также имеет значение true, поскольку hard не найден в javaIsSmart.

    В этом разделе вы изучили увеличение, уменьшение и оператор НЕ с использованием одного операнда. Несмотря на то, что эти операторы имеют только один операнд, их использование может быть сложным, как показано на примере оператора NOT. На следующем этапе вы будете опираться на эти знания, используя операторы с двумя операндами.

    Бинарные операторы

    Бинарные операторы действуют на два операнда и обычно связаны с арифметическими операциями, такими как сложение и вычитание. Существуют также другие бинарные операторы, не связанные с математикой, такие как логические операторы и специальный реляционный оператор instanceof. В этом разделе вы начнете с арифметических бинарных операторов, которые могут быть вам знакомы.

    Арифметические бинарные операторы

    Это хорошо известные операторы, используемые для арифметических операций, таких как сложение (+) и вычитание (-). Вот пример с дополнением:

    1. int theAnswer = 40 + 2;
    2. System.out.println("The result is: " + theAnswer);

    В первой строке вы добавляете 40 к 2 и присваиваете результат переменной theAnswer. Когда вы его распечатаете, вы получите окончательное значение 42:

    Output
    The result is: 42

    **ПРИМЕЧАНИЕ.**В дополнение к арифметическим операциям знак плюс (+) также используется для объединения строк. Вы видели его в действии в большинстве наших примеров с выводом значений, таких как приведенный выше. Там, используя знак плюс, вы соединили Результат: с переменной theAnswer. Однако такое использование знака плюс является исключением, и никакие другие арифметические операторы не могут использоваться аналогичным образом для ссылочных типов. Так, например, вы не можете использовать знак минус для удаления частей строки.

    Для дополнительной практики попробуйте использовать другие арифметические операторы, которые вы можете найти в документации по Java.

    Операторы присваивания

    Операторы присваивания присваивают левому операнду значение правого операнда. Обычно левый операнд является переменной, а правый — значением или ссылкой на объект. Это может показаться знакомым, потому что вы использовали такие присваивания во всех своих примерах. В этом разделе вы попрактикуетесь в использовании основного оператора присваивания, некоторых составных операторов присваивания и оператора приведения типов.

    Базовый оператор присваивания (=) — хорошо известный и часто используемый оператор.

    1. int x = 1;

    В этом примере вы объявляете переменную int x и присваиваете ей значение 1. Использование знака равенства (=) — это то, как вы присваиваете значение переменной.

    Составные операторы присваивания

    Операторы составного присваивания (+=, -=, *=, \=) сочетают присваивание с дополнительные арифметические операции, такие как сложение или вычитание. Эти операторы позволяют избежать стандартного кода, особенно в арифметических операциях, которые легко понять и выполнить.

    Например, используйте составной оператор присваивания +=, чтобы объединить сложение и присваивание следующим образом:

    1. int x = 1;
    2. int y = 1;
    3. x += y;
    4. System.out.println("x is: " + x);

    В первых двух строках вы объявляете две целочисленные переменные с именами x и y, обе со значением 1. Затем вы переназначаете x, используя составное назначение +=, что означает, что x добавляется к y, а затем присваивается обратно x.

    Приведенный выше код вернет вывод, подобный этому:

    Output
    x ==> 1 y ==> 1 $11 ==> 2 x is: 2

    Согласно приведенному выше выводу, x и y получают значение 1. В третьей строке есть временная переменная со случайно назначенным именем ($11). Он содержит значение x в результате операции составного присваивания. В последней строке выводится значение x: 2.

    Тот же самый код можно переписать без составного оператора присваивания следующим образом:

    1. int x = 1;
    2. int y = 1;
    3. x = x + y;
    4. System.out.println("x is: " + x);

    В отличие от предыдущего примера, вы пишете дополнительный код для явного описания добавления x плюс y в строке 3.

    Запуск этого кода вернет следующий вывод:

    Output
    x ==> 1 y ==> 1 x ==> 2 x is: 2

    В конечном итоге в обоих примерах x равно 2. Однако во втором примере jshell не напечатал имя временной переменной, такое как $11. Вместо этого он использовал x напрямую, чтобы показать, что его значение изменилось (x ==> 2). Такой подробный вывод очень полезен для обучения и доступен только в jshell.

    Остальные составные операторы объединяют вычитание (-=), умножение (*=) и деление (/=) вместе с присваиванием. Попробуйте изменить приведенные выше примеры, чтобы увидеть, как они могут работать.

    Полезно знать о составных операторах, потому что они часто используются. Однако от их использования нет никакого выигрыша в производительности, поэтому использование составных операторов — это вопрос личного выбора. Если они кажутся излишне запутанными, вам не нужно их использовать.

    Оператор кастинга

    Последний оператор присваивания, который вы рассмотрите, — это оператор приведения, представляющий собой тип данных, заключенный в круглые скобки: (тип данных). Оператор приведения используется для приведения значений, которые интерпретируют один тип данных как другой.

    Однако типы данных должны быть совместимы. Совместимость одного типа данных с другим определяется их отношением, например, является ли один класс родителем или братом по отношению к другому. Например, вы можете преобразовать int в short, поскольку оба типа данных используются для хранения целых чисел. Однако вы не можете преобразовать int в boolean, поскольку эти два типа данных несовместимы.

    В этом разделе вы познакомитесь с некоторыми распространенными примерами и проблемами, связанными с приведением типов. В образовательных целях вы начнете с неправильного и несовместимого приведения:

    1. boolean y = (boolean) 1;

    В этой строке вы пытаетесь преобразовать целое число 1 в логическое значение и присвоить его переменной y. Когда вы вставите это в jshell, вы получите следующую ошибку:

    Output
    | Error: | incompatible types: int cannot be converted to boolean | boolean y = (boolean) 1; |

    Как поясняется в сообщении об ошибке, вы не можете преобразовать значение int в boolean. Логические значения могут быть либо true, либо false, и невозможно определить, каким должно быть логическое значение 1.

    Теперь вы попробуете пример с совместимыми типами данных. Вы будете использовать два примитивных типа для хранения целых чисел: int и short. Разница заключается в их емкости, то есть в объеме памяти, доступной для хранения информации. int имеет большую емкость и, следовательно, может хранить большие числа.

    Добавьте следующие строки в jshell:

    1. int prize = 32767;
    2. short wonPrize = (short) prize;
    3. System.out.println("You won: " + wonPrize);

    В первой строке вы определяете лотерейный приз как примитивный тип int со значением 32767. Однако во второй строке вы решаете, что примитивный тип short будет более подходящим для значения winprize, и вы приводите prize на short с помощью (short).

    Когда вы запускаете приведенный выше код в jshell, вывод будет таким:

    Output
    prize ==> 32767 wonPrize ==> 32767 You won: 32767

    Приведенный выше вывод подтверждает, что значения prize и wonPrize были правильно установлены на 32767. В последней строке используется переменная wonPrize, чтобы указать, сколько вы выиграли.

    В случае int и short приведение может показаться ненужным, и вы, вероятно, не увидите такого приведения в реальности. Однако этот пример полезен для демонстрации идеи приведения типов.

    Кастинг кажется простым, но есть один нюанс. При преобразовании типа данных с большей емкостью к типу данных с меньшей емкостью вы можете превысить ограничение на меньшую емкость, что называется переполнением. Чтобы продемонстрировать эту проблему, повторно используйте предыдущий пример и увеличьте приз с 32767 до 32768, например:

    1. int prize = 32768;
    2. short wonPrize = (short) prize;
    3. System.out.println("You won: " + wonPrize);

    Когда вы запустите вышеописанное в jshell, вы получите следующий вывод:

    Output
    prize ==> 32768 wonPrize ==> -32768 You won: -32768

    В этом случае вы теряете информацию и получаете неожиданные результаты. При приведении к short значение 32768 становится -32768. Это связано с тем, что емкость хранилища short находится в диапазоне от -32768 до 32767. Когда вы пытаетесь сохранить значение, превышающее максимальное значение, вы переполняете его и начинаете с самого начала. В этом случае вы превысите максимальную емкость (32767) на 1 при попытке сохранить 32768. Из-за этого присваивается следующее значение, начиная с наименьшего возможного. В данном случае это минимальное значение -32768.

    Вот почему приведенный выше вывод кажется неожиданным — окончательный приз стал отрицательным числом. Такого рода проблемы не всегда легко обнаружить, поэтому вы должны использовать приведение типов с осторожностью. Вы можете использовать приведение типов в более сложных сценариях, которые будут рассмотрены в будущих руководствах из серии Java.

    Реляционные операторы

    Реляционные операторы сравнивают два операнда и возвращают логический результат. Если отношение установлено, результатом будет true. Если нет, результатом будет false.

    Первые типы реляционных операторов равны == и не равны !=. Они используются для утверждения равенства ценностей и объектов. С примитивными значениями и литералами их использование похоже на математику.

    Чтобы продемонстрировать оператор равенства, сравните два целочисленных литерала. Фактически это будет одно и то же число: 1. Вы сравните, равен ли он самому себе, чтобы получить результат true. Вставьте следующий код в jshell:

    1. System.out.println(1==1);

    В приведенном выше коде вы проверяете, равен ли 1 1. Поскольку числа равны, это выражение оценивается как истинное. Таким образом, println() выводит true:

    Output
    true

    В качестве упражнения попробуйте изменить одно из значений, чтобы получить ложный результат.

    Примечание. Обязательно различайте оператор равенства == и оператор присваивания =. Даже когда вы знаете, что они разные, их легко спутать. Вы не всегда можете получить синтаксическую ошибку в своем коде, что может привести к проблемам, которые трудно отладить.

    В отличие от сравнения примитивных значений, сравнение объектов на равенство является более сложным, поскольку вы устанавливаете, указывают ли две переменные на один и тот же объект. Попробуйте сравнить два Integer в качестве примера:

    1. Integer myAnswer = Integer.valueOf(42);
    2. Integer yourAnswer = Integer.valueOf(42);
    3. System.out.println(myAnswer == yourAnswer);

    В приведенном выше коде вы создаете две переменные Integer, каждая со значением 42. В последней строке вы сравниваете их на равенство и печатаете true, если они равны. Из нашего предыдущего руководства «Понимание типов данных в Java» вы, возможно, знаете, что Integer.valueOf() сначала проверяет кеш на наличие объекта с таким же значением и возвращает тот же объект, если он уже есть с этим значением. . Вот как и myAnswer, и yourAnswer получают один и тот же объект.

    Когда вы вставите приведенный выше код в jshell, вы получите следующий вывод:

    Output
    myAnswer ==> 42 yourAnswer ==> 42 true

    Такое сравнение объектов кажется простым, но иногда это сложно. Самый запутанный пример со строками. Попробуйте сравнить две строки с одинаковыми значениями:

    1. String answer1 = new String("yes");
    2. String answer2 = new String("yes");
    3. System.out.println(answer1 == answer2);

    Сначала вы объявляете две новые переменные String (answer1 и answer2) со значениями yes. Однако вы использовали ключевое слово new для создания новых объектов String. Из-за этого две переменные не указывают на один и тот же объект — они фактически указывают на два разных объекта (с одним и тем же значением).

    Когда вы вставите приведенный выше код в jshell, вы получите следующий вывод:

    Output
    answer1 ==> "yes" answer2 ==> "yes" false

    Несмотря на то, что answer1 и answer2 имеют одинаковое значение (yes), их равенство оценивается как false, значит они не равны. Это может сбивать с толку, если вы собираетесь сравнивать значения, например, являются ли оба ответа утвердительными, и вас не интересуют лежащие в их основе объекты. Для этой цели многие классы, включая String, имеют специальные методы для подтверждения равенства.

    В случае String это метод equals(). Попробуйте изменить код, чтобы использовать equals() (вместо ==), например:

    1. String answer1 = new String("yes");
    2. String answer2 = new String("yes");
    3. System.out.println(answer1.equals(answer2));

    Метод equals() проверяет, равны ли строки, содержащиеся в сравниваемых объектах.

    Когда вы вставите этот код в jshell, вы получите следующий вывод:

    Output
    answer1 ==> "yes" answer2 ==> "yes" true

    Приведенный выше вывод аналогичен предыдущему выводу, но заканчивается true, подтверждая, что значения двух объектов равны. Этот пример демонстрирует, что вы должны быть осторожны при сравнении ссылочных типов и использовать соответствующие методы, когда они доступны.

    Альтернативный оператор равенства, not equals !=, используется аналогично, но он утверждает, что две переменные или значения не совпадают (или не равны). В качестве упражнения попробуйте заменить == на != в некоторых из предыдущих примеров.

    Подобно == и !=, следующие четыре реляционных оператора также взяты из математики: меньше <, меньше или равно <=, больше > и больше или равно =>.

    Вот пример использования оператора «больше чем»:

    1. System.out.println(4 > 5);

    Когда вы запустите этот код в jshell, вы получите следующий вывод:

    Output
    false

    Приведенный выше код сначала сравнивает, больше ли 4, чем 5. Поскольку это не так, выражение оценивается как false. Результат сравнения (false) затем печатается методом println().

    Последний реляционный оператор — это instanceof, который оценивает, является ли переменная экземпляром данного класса (или подкласса) или реализацией интерфейса. Как объяснялось в нашем учебнике «Понимание типов данных в Java», интерфейс — это абстрактная сущность с группой требований.

    Используйте следующий пример, чтобы изучить, как работает instanceof:

    1. String greeting = "hello";
    2. System.out.println(greeting instanceof String);

    Сначала вы создаете переменную String с именем greeting. Затем в скобках вы оцениваете, является ли greeting экземпляром String.

    Когда вы вставите код в jshell, вы получите следующий вывод:

    Output
    greeting ==> "hello" true

    Поскольку greeting является экземпляром String, выражение оценивается как true, которое выводится на экран с помощью println().

    Логические операторы

    Логические операторы: логическое И (&), логическое ИЛИ (|) и исключающее OR. (^). Все они оценивают два значения следующим образом:

    • Логическое И истинно, если оба значения true.
    • Логическое ИЛИ верно, если хотя бы одно из значений равно true.
    • Исключающее OR имеет значение true, если одно значение равно true, а другое — false.

    Когда логические операторы неверны в соответствии с приведенными выше условиями, они ложны.

    Чтобы использовать логический оператор И (&), вставьте следующий пример в jshell:

    1. boolean isJavaFun = true;
    2. boolean isJavaPowerful = true;
    3. System.out.println(isJavaFun & isJavaPowerful);

    Первые две строки определяют переменные boolean isJavaFun и isJavaPowerful в значение true. В третьей строке в круглых скобках вы выполняете логическую операцию И над isJavaFun и isJavaPowerful, и результат печатается с помощью println( ).

    Когда вы вставите этот код в jshell, вы получите следующий вывод:

    Output
    isJavaFun ==> true isJavaPowerful ==> true true

    Обеим переменным присваивается значение true, а итоговое значение true выводится как результат логической операции AND.

    Чтобы расширить свои навыки, попробуйте использовать предыдущий пример кода с некоторыми вариациями. Вы можете попробовать переключить значения переменных между true и false. Вы также можете попробовать изменить логические операторы на логическое ИЛИ (|) и исключающее ИЛИ (^).

    Расширенной версией логических операторов являются так называемые логические операторы короткого замыкания: короткое замыкание AND (&&) и короткое замыкание OR (||). Они похожи на обычные логические операторы И и ИЛИ, но имеют одно важное отличие: если для операции достаточно вычисления первого оператора, то второй не вычисляется. . Таким образом, чтобы короткое замыкание AND было истинным, обе стороны, окружающие его, должны быть true. Однако, если левая сторона имеет значение false, правая сторона не оценивается. Аналогично, с помощью короткого замыкания ИЛИ, если левая сторона имеет значение false, правая не оценивается.

    Вот пример с коротким замыканием OR:

    1. boolean isJavaFun = true;
    2. Boolean isNullFun = null;
    3. System.out.println(isJavaFun || isNullFun);

    Во-первых, вы присваиваете переменной isJavaFun значение true. Для совместимости с предыдущими примерами эта переменная имеет примитивный тип boolean. Однако для следующей переменной, isNullFun, вы используете тип ссылки Boolean, чтобы можно было присвоить ей значение null. Например, важно, чтобы у вас была указывающая переменная null, но, как вы помните из учебника «Понимание типов данных Java», типы примитивов не могут быть нулевыми, поэтому вы используете ссылочный тип. .

    Когда в скобках происходит короткое замыкание ИЛИ, isNullFun игнорируется, поскольку левая часть равна true, и этого достаточно для всего выражения быть true. Таким образом, когда вы запускаете код в jshell, будет напечатан следующий вывод:

    Output
    isJavaFun ==> true isNullFun ==> null true

    Первая и вторая строки подтверждают, что переменным присвоены значения true и null. В третьей строке выводится true, поскольку операция короткого замыкания OR вернула true.

    Приведенный выше пример был специально выбран с null, чтобы продемонстрировать, как работают операторы короткого замыкания, и что isNullFun не будет оцениваться. Чтобы увидеть оценку isNullFun, попробуйте заменить OR на обычный OR следующим образом:

    1. boolean isJavaFun = true;
    2. Boolean isNullFun = null;
    3. System.out.println(isJavaFun | isNullFun);

    Обычное логическое ИЛИ оценивает обе части выражения.

    Когда вы запустите этот код в jshell, вы получите следующий вывод:

    isJavaFun ==> true
    isNullFun ==> null
    |  Exception java.lang.NullPointerException
    |        at (#3:1)
    

    Когда логическое ИЛИ пытается оценить null, вы получаете java.lang.NullPointerException. Из-за этого предпочтительны операторы короткого замыкания, и они почти всегда используются вместо обычных логических операторов.

    В качестве упражнения потренируйтесь использовать сокращенные коды && и ||, которые являются наиболее популярными и полезными из всех.

    В этом разделе вы использовали бинарные операторы в ряде примеров, от базовой арифметики до более сложных операций, включающих приведение и сравнение объектов на равенство. В следующем разделе вы будете работать с тремя операндами.

    Тернарный оператор

    В предыдущих разделах вы практиковались в использовании операторов с одним и двумя операндами. В этом заключительном разделе вы будете использовать тернарный оператор, единственный оператор для трех операндов. Его синтаксис таков: первый операнд ? второй операнд : третий операнд. Первый операнд должен быть логическим. Если оно равно true, то из выражения возвращается второй операнд. Если первый операнд false, возвращается третий операнд.

    Тернарный оператор популярен и часто используется, потому что он может избавить вас от написания сложных операторов, таких как условные операторы, и сохранения их результатов во временных переменных.

    Попробуйте тернарный оператор со следующим примером:

    1. boolean isJavaFun = true;
    2. String shouldILearnJava = isJavaFun ? "yes" : "no";
    3. System.out.println("Should I learn Java: " + shouldILearnJava);

    isJavaFun имеет значение true, и переменная shouldILearnJava определяется им в тернарной операции. Поскольку первый операнд, isJavaFun, имеет значение true, возвращается второй операнд, представляющий собой строку yes. Чтобы убедиться в этом, третья строка выводит переменную shouldILearnJava, которая на данном этапе должна быть yes.

    Когда вы запустите приведенный выше код, вы получите следующий вывод:

    Output
    Should I learn Java: yes

    Для дополнительной практики попробуйте использовать оператор NOT перед isJavaFun:

    1. boolean isJavaFun = true;
    2. String shouldILearnJava = !isJavaFun ? "yes" : "no";
    3. System.out.println("Should I learn java: " + shouldILearnJava);

    Меняя значение isJavaFun, вы устанавливаете его с true на false. В результате тернарное выражение вернет последний операнд, который равен no.

    Тернарные выражения могут сбивать с толку, особенно если вы используете дополнительные операторы, такие как оператор NOT. Тем не менее, они могут сэкономить вам часть стандартного кода, и именно поэтому они популярны.

    Приоритет оператора

    Как только вы узнаете важные операторы, вы сможете их использовать и даже комбинировать. Но прежде чем вы начнете их комбинировать, вам необходимо знать правила приоритета операторов.

    Приоритет оператора определяет, в каком порядке оцениваются операторы. Поскольку вы, вероятно, будете использовать более одного оператора, важно понимать приоритет операторов. Хотя правила не всегда интуитивно понятны, на практике вам, скорее всего, потребуется знать лишь несколько основных правил.

    Понимание приоритета операторов помогает писать чистый код, который де-факто является стандартом современного программирования. Писать чистый код означает писать понятный и удобный для сопровождения код. Что касается операторов, парадигма чистого кода означает использование как можно меньшего количества операторов и создание отдельных операторов вместо вложения и объединения операторов.

    Например, следует избегать таких утверждений, как приведенное ниже, потому что они слишком запутывают:

    1. boolean isThisCleanCode = !true || false && true;

    Даже если вы обратитесь к документации оператора, вы не сможете угадать конечный результат (isThisCleanCode равно false).

    Вот некоторые из наиболее важных и часто используемых правил приоритета, начиная с правил с наивысшим приоритетом:

    • Предварительные и после операторы увеличения и уменьшения: они имеют наивысший приоритет и вступают в силу перед любыми другими операторами.
    • Арифметические правила из математики. Все правила, действительные в математике, действительны и в Java. Например, деление / имеет более высокий приоритет, чем сложение +. Скобки переопределяют приоритет; то есть вы можете группировать операции скобками, и они будут оцениваться с приоритетом.
    • Операции равенства и отношения. Поскольку они оценивают равенство или отношение, они также работают с конечными значениями своих операндов, поэтому все остальные операции должны быть завершены.
    • Логические операторы ИЛИ и И (включая короткое замыкание). Как и в случае с тернарным оператором, всем им нужны окончательные значения своих операндов, поэтому у них низкий приоритет.
    • Тернарный оператор. Тернарному оператору требуется конечное значение первого операнда. Для этого должны быть завершены все остальные операции. Вот почему тернарный оператор имеет такой низкий приоритет.
    • Операторы присваивания. Они оцениваются последними, чтобы все остальные операции были завершены и окончательный результат можно было присвоить операнду слева. В качестве примера подумайте о каждой переменной, которой вы до сих пор присваивали знак равенства.

    Теперь вы будете использовать математическую задачу для изучения приоритета операторов:

    1. int x = 1 + 10 / 2;

    Когда вы вставите приведенный выше код в jshell, вы получите следующий вывод:

    Output
    x ==> 6

    Согласно приведенному выше выводу, x получает значение 6. Это связано с тем, что следующие операции были выполнены с понижением приоритета:

    1. 10/2 оценивается первым. В результате получается 5.
    2. 1 добавляется к результату первой операции (5). В результате получается 6.
    3. В игру вступает оператор присваивания, который использует окончательный результат (6), чтобы присвоить его переменной x.

    Несмотря на то, что это математическое уравнение относительно простое, вы всегда можете сделать его более подробным и убедиться, что приоритет легко понятен, используя круглые скобки. Попробуйте переписать его так:

    1. int x = 1 + (10 / 2);

    Когда вы вставите приведенное выше в jshell, будет напечатан тот же результат, что и раньше:

    Output
    x ==> 6

    В последнем примере вы не меняли приоритет, используя круглые скобки вокруг 10/2. Вместо этого их цель состояла только в том, чтобы сделать более очевидным приоритет операции внутри них. Использование подобных круглых скобок помогает сделать ваш код более чистым и понятным, что особенно важно, когда операции более сложны.

    Правила приоритета интересны, и потратить некоторое время на их изучение — хорошая идея. Помните о парадигме чистого кода и учитывайте тот факт, что ненужная вложенность и комбинирование операторов рассматривается как слабость кода.

    Заключение

    В этом руководстве вы узнали об основных операторах в Java. Вы написали несколько тестовых фрагментов кода, в которых увидели несколько наиболее полезных и интересных сценариев, связанных с операторами. Вы также узнали о чистоте кода и о том, что операторы не следует использовать без необходимости.

    Чтобы узнать больше о Java, ознакомьтесь с нашей серией статей How To Code in Java.