Тернарный оператор в Java, пример использования

Привет! Сегодняшняя лекция будет не очень большой, но совершенно точно полезной 🙂 Мы поговорим о так называемом тернарном операторе.
Тернарный” в переводе означает “тройной”. Это альтернатива условному оператору if-else, с которым ты уже знаком.

Приведем пример. Допустим, какой-то человек решил пойти в кино на фильм с рейтингом 18+. Охранник проверяет его возраст на входе: если он проходит по возрасту — позволяет пройти в зал, если нет — отправляет домой.

Создадим класс Man и проверим это с помощью if-else:

public class Man {

   private int age;

   public Man(int age) {
       this.age = age;
   }

   public int getAge() {
       return age;
   }

   public void setAge(int age) {
       this.age = age;
   }

   public static void main(String[] args) {

       Man man = new Man(22);

       String securityAnswer;

       if (man.getAge() >= 18) {
           securityAnswer = "Все в порядке, проходите!";
       } else {
           securityAnswer = "Этот фильм не подходит для вашего возраста!";
       }

       System.out.println(securityAnswer);

   }
}

Вывод в консоль:

«Все в порядке, проходите!»

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

if (man.getAge() >= 18) {
           securityAnswer = "Все в порядке, проходите!";
       } else {
           securityAnswer = "Этот фильм не подходит для вашего возраста!";
       }

Здесь, по сути, работает простая логика: проверяется одно условие (возраст > 18). В зависимости от этого в переменную securityAnswer присваивается одна из двух строк с ответом охранника.

Такие ситуации, “одно условие — два возможных результата”, встречаются в программировании очень часто. Поэтому для них создали тот самый тернарный оператор.

С его помощью мы можем упростить нашу проверку до одной строки кода:

public static void main(String[] args) {

   Man man = new Man(22);

   String securityAnswer = (man.getAge() > 18) ? "Все в порядке, проходите!" : "Этот фильм не подходит для вашего возраста!";

   System.out.println(securityAnswer);

}

Так и выглядит работа этого оператора. Тернарным (тройным) его называют потому, что в его работе принимают участие 3 компонента:

  • Одно условие (man.getAge() > 18)
  • Два возможных результата («Все в порядке, проходите!» и «Этот фильм не подходит для вашего возраста!»)

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

man.getAge() > 18 ?

“Возраст человека больше 18?”

Далее следует первый результат. Он срабатывает в случае, если условие возвращает true, то есть является истинным:

String securityAnswer = man.getAge() > 18 ? "Все в порядке, проходите!"

Возраст человека больше 18? Если да — присвоить переменной securityAnswer значение «Все в порядке, проходите!».

Далее следует оператор “:” , после которого записывается второй результат. Он срабатывает в случае, если условие возвращает false, то есть является ложным:

String securityAnswer = man.getAge() > 18 ? "Все в порядке, проходите!" : "Этот фильм не подходит для вашего возраста!";

Возраст человека больше 18? Если да — присвоить переменной securityAnswer значение «Все в порядке, проходите!». Если нет — присвоить переменной securityAnswer значение «Этот фильм не подходит для вашего возраста!»

Вот так и выглядит общая логика тернарного оператора.

условие ? результат 1 : результат 2
Кстати, скобки вокруг условия ставить не обязательно: мы сделали это для большей читаемости. Сработает и без них:

public static void main(String[] args) {

   Man man = new Man(22);

   String securityAnswer = man.getAge() > 18 ? "Все в порядке, проходите!" : "Этот фильм не подходит для вашего возраста!";

   System.out.println(securityAnswer);

}

Что же все-таки использовать: if-else, или тернарный оператор?

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

Здесь вопрос относится скорее к читаемости твоего кода.

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

Общая рекомендация может звучать так: если условие простое и легко проверяется, можно без ущерба использовать тернарный оператор. Таким образом ты сократишь объем кода и количество проверок if-else, которых там и без того может быть немало.

А вот если условие является сложным и многоступенчатым — лучше использовать if-else.

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

String securityAnswer = (man.getAge() > 18 && (man.hasTicket() || man.hasCoupon()) && !man.hasChild())  ? "Проходите!" : "Вы не можете пройти!";

Так сходу и не поймешь, что тут происходит! Код стал очень сложным для чтения.

А все из-за сложного условия:

  • Если человеку больше 18 лет + у него есть билет (или у него есть купон на бесплатное посещение) + с ним нет маленьких детей — тогда он может пройти.
  • Если хотя бы одна из частей условия возвращает false — тогда не может.

Вот здесь явно лучше бы подошло использование if-else. Да, наш код стал бы побольше в размерах, но он был бы в разы более читаемым. И никто из коллег не схватится за голову, если такой код достанется ему в наследство 🙂

Напоследок могу порекомендовать тебе книгу. Мы затронули в лекции тему читаемости кода. Ей посвящена ставшая классикой книга “Чистый код” Роберта Мартина.
В ней собраны лучшие практики и рекомендации для программистов, которые позволят тебе писать не только работающий, но и легко читаемый код.

Обзор этой книги есть на JavaRush.

javarush.ru

Условные операторы Java | Java master

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

Давайте разберем, что это за оператор. Синтаксис оператора такой:

if (условие истинно) {

выполняем все, что находиться в этих блоках

}

else {

выполняем все что здесь

}

Есть еще такой вид этого оператора:

if (условие истинно) {

выполняем все, что находиться в этих блоках

}

else if (это условие истинно){

выполняем код здесь

}

else {

выполняем все что здесь

}

Вы можете добавлять сколько угодно else if конструкций и проверять любое количество условий. Но когда условий очень много лучше использовать другой оператор: switch — case.

Его синтаксис следующий:

switch (ключ) {
case значение ключа:
выполняем этот код
break;

//сколько угодно блоков case

default:

если значений ключа не оказалось в case блоках — выполняем этот блок кода
break;
}

На примерах все станет ясней.

Давайте создадим класс ConditionalOperators и попробуем потренироваться писать условные операторы. Если Вы не знаете, как создать класс, то советую почитать статью: Первая программа на Java.

Нашей первой задачей будет проверить переменную на знак: больше 0, меньше 0, или равно 0.

  1. public class ConditionalOperators {

  2.  

  3.     public static void main(String[] args) {
  4.         //допустим у нас есть переменная variable

  5.         //которая по умолчанию равна 5

  6.         int variable = 5;

  7.         //мы прибавляем к ней число и хотим узнать:

  8.         //стала эта переменная больше 0, меньше 0 или 0

  9.         //думаю задача понятна

  10.         variable = variable + 3;//очевидно, что переменная станет больше 0

  11.         //давайте это проверим

  12.         if (variable > 0) {

  13.             System.out.println(«Переменная больше 0»);
  14.         }

  15.         else if (variable < 0) {

  16.             System.out.println(«Переменная меньше 0»);
  17.         }

  18.         else {

  19.             System.out.println(«Переменная равна 0»);
  20.         }

  21.     }

  22.  

  23. }

Я предлагаю Вам самим запустить этот код и попробовать поменять значение на которое прибавляется переменная на -3 и -5. Вы уведите, что наша программа отлично работает.

А что если нам нужно проверять не одно условие а несколько условий одновременно? Это не проблема. В Java есть операторы, которые позволяют нам проверить одновременно несколько условий: &&, ||. Эти непонятные значки соответствуют выражениям (и, или).

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

  1. public class ConditionalOperators {

  2.  

  3.     public static void main(String[] args) {
  4.         //у нас есть прежняя переменная variable

  5.         //которая по умолчанию равна 5

  6.         int variable = 5;

  7.         //и есть переменная variable2 которая = 4.3

  8.         double variable2 = 4.3;

  9.  

  10.         variable = variable + 3;

  11.         variable2 = variable2 — 6;

  12.        

  13.         if (variable > 0 && variable2 > 0) {

  14.             System.out.println(«Переменные больше 0»);
  15.         }

  16.         else if (variable < 0 && variable2 < 0) {

  17.             System.out.println(«Переменные меньше 0»);
  18.         }

  19.         else {

  20.             System.out.println(«Нужно больше проверок»);
  21.         }

  22.     }

  23.  

  24. }

Если Вы запустите данный код, то увидите последнее сообщение о том, что нужно больше проверок. Это потому, что наши переменные имеют разные знаки. Предлагаю Вам дописать это приложение, чтобы проверить все возможные варианты. Вы уже догадались, что знак && проверяет на истинность  два выражение и результатом будет true если только два выражения будут true (верны). Давайте посмотрим все варианты проверок:

  1. //Выражение и

  2.         System.out.println(true&&true);
  3.         System.out.println(true&&false);
  4.         System.out.println(false&&false);
  5.         System.out.println(false&&true);
  6.        

  7.         //Выражение или

  8.         System.out.println(true||true);
  9.         System.out.println(true||false);
  10.         System.out.println(false||false);
  11.         System.out.println(false||true);

Результат:

true
false
false
false
true
true
false
true

В некоторых источниках и тестах в будущем Вы можете увидеть вот такую запись этих операторов: &, |. Что это означает? Разница между парными значками и непарными в том, что непарные проверяют два выражения, даже если исход известен, а парные проверяют при надобности только первое выражение. Например false&&false. В этом выражении можно не проверять вторую часть, так как исход всегда будет ложь если в выражении «и» присутствует ложь. «Мы пойдем гулять если будет светло и хорошее настроение.» Если на улице не светло, то проверять есть ли хорошее настроение просто нет смысла. Вот так и в программе. Операторы && и || проверяют только одно выражение при надобность, в то время как & |  проверяют все два в независимости от исхода.

Теперь настало время попрактиковаться с switch-case оператором. Для неопытных и начинающих программистов он может показаться немного сложным и запутанным, по сравнению с if-else. Но это на первый взгляд. Со временем, Вы научитесь им пользоваться в совершенстве. Он, по правде сказать, используется не так часто, как if-else, но бывают ситуации, когда этот оператор очень полезен.

Возьмем все тот же класс ConditionalOperators и допишем в методе мейн пример switch-case. Допустим, нам надо выводить день недели в зависимости от числа, которое поступает на вход. Вот как можно это организовать с помощью  switch-case оператора.

  1. int variable = 2;

  2.         switch (variable) {

  3.         case 1:

  4.             System.out.println(«Понедельник»);
  5.             break;

  6.         case 2:

  7.             System.out.println(«Вторник»);
  8.             break;

  9.         case 3:

  10.             System.out.println(«Среда»);
  11.             break;

  12.         case 4:

  13.             System.out.println(«Четверг»);
  14.             break;

  15.         case 5:

  16.             System.out.println(«Пятница»);
  17.             break;

  18.         case 6:

  19.             System.out.println(«Суббота»);
  20.             break;

  21.         case 7:

  22.             System.out.println(«Воскресенье»);
  23.             break;

  24.         default: System.out.println(«Неверное число»);
  25.             break;

  26.         }

 

Ответ будет: Вторник.

Так как у нас переменной задано значение 2, которое отвечает выражению вывести вторник. Пока мы не добрались до потоков ввода-вывода, то не сможем вводить с консоли и делать нашу программу интересной. НО. Давайте я просто покажу часть кода, с помощью которой можно будет вводить с консоли (как я это сделал с выводом) и можно будет не хардкодить наши переменные, а вводить с консоли. Так программировать будет интересней и базовые понятия будут не так скучны.

Для ввода с консоли можно использовать класс Scanner. Вот наша программа, но уже с дополнениями:

  1. System.out.println(«Введите число»);
  2.        

java-master.com

Switch case Java / Оператор switch в Java

Немного теории

Представьте, что вы стоите на развилке, как богатырь с известной картины. Налево пойдёшь — коня потеряешь, направо пойдешь — знания обретёшь. Как запрограммировать такую ситуацию? Вы уже, скорее всего, знаете, что подобный выбор мы совершаем с помощью конструкций if-then и if-then-else.

if (turn_left) {
    System.out.println(«Коня потеряешь»);
}
if (turn_right) {
    System.out.println(“Знания обретёшь”);
}
else
    System.out.println(“Так и будешь стоять?”);

А что, если таких дорожек не две, а 10? Есть дорожка «совсем направо», «чуть левее», «ещё чуть-чуть левее» и так далее, в количестве 10 штук?

Представьте, как разрастётся ваш if-then-else код в таком варианте!

if (вариант1)
{… }
else if (вариант2)
{…}
…
else if (вариантN) ….

Итак, у вас не одна развилка условий, а несколько, скажем, 10 (тут важно, что число развилок ограничено). Для таких ситуаций есть специальный оператор выбора — switch case java.

switch (ВыражениеДляВыбора) {
           case  (Значение1):
               Код1;
               break;
           case (Значение2):
               Код2;
               break;
...
           case (ЗначениеN):
               КодN;
               break;
           default:
               КодВыбораПоУмолчанию;
               break;
       }

Порядок выполнения в операторе следующий:

  • Вычисляется ВыражениеДляВыбора. Далее оператор switch сравнивает полученное выражение с очередным Значением (в порядке перечисления).
  • Если ВыражениеДляВыбора совпало со Значением, то выполняется код, идущий после двоеточия.
  • Если встречается конструкция break — то управление передается за пределы команды switch.
  • Если совпадений ВыражениеДляВыбора и Значений не выявлено, то управление передаётся КодуВыбораПоУмолчанию.

Важные моменты

Перейдем к практике использования оператора switch в Java

Не волнуйтесь, с теорией покончили, и, после дальнейших примеров станет всё гораздо понятнее. Итак, приступим.
Давайте рассмотрим пример из астрономии о планетах Солнечной системы.

В соответствии с последними международными положениями исключим Плутон (за свойства ее орбиты). Вспомним, что планеты у нас расположены от Солнца в следующей последовательности: Меркурий, Венера, Земля, Марс, Юпитер, Сатурн, Уран и Нептун.

Создадим Java метод, который получает на вход порядковый номер планеты (относительно удалённости от Солнца), а на выходе выдает основной состав атмосферы этой планеты в виде списка List<String>.

Напомню, у некоторых планет – схожий состав атмосферы. Так, Венера и Марс содержат в основном углекислый газ, у Юпитера и Сатурна она состоят из водорода и гелия, а Уран и Нептун вдобавок к последней паре газов также имеет метан.

Наша функция:

public static List<String> getPlanetAtmosphere(int seqNumberFromSun) {
    List<String> result = new ArrayList<>();
    switch (seqNumberFromSun) {
        case 1: result.add("Нет атмосферы");
            break;
        case 2:
        case 4: result.add("Углекислый газ");
            break;
        case 3: result.add("Углекислый газ");
            result.add("Азот");
            result.add("Кислород");
            break;
        case 5:
        case 6: result.add("Водород");
            result.add("Гелий");
            break;
        case 7:
        case 8: result.add("Метан");
            result.add("Водород");
            result.add("Гелий");
            break;
        default:
            break;
    }
    return result;
}

Обратите внимание: идентичным по составу атмосфер планетам мы сопоставили один и тот же код. А сделали мы это за счёт подряд идущих конструкций case.

Итого, если мы хотим получить состав атмосферы нашей с вами родной планеты, вызываем наш метод с параметром 3:

getPlanetAtmosphere(3).
System.out.println(getPlanetAtmosphere(3)) вернет нам [Углекислый газ, Азот, Кислород].

Эксперимент с break

Что получится, если мы уберем все операторы break? Попробуем на практике:

public static List<String> getPlanetAtmosphere(int seqNumberFromSun) {
    List<String> result = new ArrayList<>();
    switch (seqNumberFromSun) {
        case 1: result.add("Нет атмосферы");
        case 2:
        case 4: result.add("Углекислый газ");
        case 3: result.add("Углекислый газ");
            result.add("Азот");
            result.add("Кислород");
        case 5:
        case 6: result.add("Водород");
            result.add("Гелий");
        case 7:
        case 8: result.add("Метан");
            result.add("Водород");
            result.add("Гелий");
        default:
    }
    return result;
}

Если мы распечатаем результат работы метода System.out.println(getPlanetAtmosphere(3)), то наша родная планета окажется не такой уж пригодной для жизни. Или пригодной? Судите сами:

[Углекислый газ, Азот, Кислород, Водород, Гелий, Метан, Водород, Гелий],

Почему так получилось? Программа выполнила все case после первого совпадения и до конца блока switch.

Излишняя оптимизация break

Заметим, что мы можем усовершенствовать метод иным расположением директив break и вариантов выбора

public static List<String> getPlanetAtmosphere(int seqNumberFromSun) {
    List<String> result = new ArrayList<>();
    switch (seqNumberFromSun) {
        case 1: result.add("Нет атмосферы");
                break;
        case 3: result.add("Азот");
                result.add("Кислород");
        case 2:
        case 4: result.add("Углекислый газ");
                break;
        case 7:
        case 8: result.add("Метан");
        case 5:
        case 6: result.add("Водород");
                result.add("Гелий");
    }
     return result;
}

Выглядит короче, не так ли? Мы сократили общее число операторов, поигравшись с порядком следования case и перегруппировкой. Теперь каждый вид газа добавляется в список только в одной строчке кода.

Листинг последнего примера метода показан только для демонстрации работы, крайне не рекомендуется писать в подобном стиле. Если автору (а тем более сторонним программистам) схожего кода предстоит его сопровождать, то будет весьма тяжело восстановить логику формирования блоков выбора и выполняемого кода для оператора switch java.

Отличия от if

При внешней схожести операторов if и switch не забывайте, что выбор вариантов выполнения оператор множественного выбора switch основывает на КОНКРЕТНОМ ЗНАЧЕНИИ, тогда как в if. может быть любое логическое выражение. Учитывайте данный факт, проектируя ваш код.

Итого

  • Используйте оператор case при числе ветвлений более двух, чтобы не загромождать if-структурами код.
  • Не забывайте завершать логический блок каждой ветки соответствующего конкретному значению (блок case) вызовом break.
  • Оператор switch помимо некоторых примитивных типов, в качестве выражения может использовать также типы Enum и String.
  • Помните про блок default – употребляйте его для обработки незапланированных значений выбора.
  • Для оптимизации производительности переместите ветки кода с наиболее часто встречающимися вариантами выбора к началу блока switch.
  • Не увлекайтесь «оптимизацией» за счёт удаления break в конце блока выбора case – такой код сложен для понимания, и, как следствие, тяжело сопровождать при его развитии.

English version of this post: Java switch statement on CodeGym

javarush.ru

Операторы и выражения в Java. Часть 2 – описание таблицы приоритетов операторов

Здесь мы подробно рассмотрим таблицу приоритетов операторов приведенную в прошлом посте.

Приоритет

В колонке P таблицы приоритетов операторов определен приоритет (precedence) для каждого оператора. Приоритет определяет порядок выполнения операторов. Рассмотрим следующее выражение:

a + b * c

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

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

(a + b) * c

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

// Приведение класса, объединенное с доступом к члену

(( Integer) o).intValue(); // Присваивание в совокупности со сравнением
while(( line = in.readLine()) != null) { … } // Побитовые операторы в совокупности со сравнением
if (( flags & (PUBLIC | PROTECTED)) != 0) { … }

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

Ассоциативность

Если выражение включает несколько операторов с одинаковым приоритетом, то порядком выполнения операций управляет ассоциативность операторов. Большинство операторов ассоциативны слева направо, то есть операции выполняются слева направо. Однако операторы присваивания и унарные операторы обратно ассоциативны (справа налево). В колонке А таблицы приоритетов операторов определена ассоциативность для каждого оператора или группы операторов. Значение L означает ассоциативность слева направо, а R означает обратную ассоциативность.

Аддитивные операторы ассоциативны слева направо, то есть выражение a+b-c вычисляется слева направо: (a+b)-c. Унарные операторы и операторы присваивания вычисляются справа налево. Рассмотрим более сложное выражение:

a = b += c = ~d

Оно вычисляется следующим образом:

a = ( b += ( c = (~d)))

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

Количество и типы операндов

В четвертой колонке таблицы приоритетов операторов определены возможные типы и количество операндов для каждого оператора. Некоторые операторы работают только с одним операндом; они называются унарными операторами. Например, оператор «унарный минус» меняет знак отдельного числа.

-n // Оператор «унарный минус»

Однако большинство операторов являются бинарными; они работают с двумя операндами. Оператор (минус) может выступать в обеих формах:

a-b // Оператор вычитания является бинарным

В Java также определен один тернарный (ternary) оператор (работает с тремя операндами), часто называемый условным оператором. Он похож на условный оператор if, но стоит внутри выражения. Эти три операнда разделяются знаком вопроса и двоеточием; второй и третий операнды должны относиться к одному типу.

x > y ? x : y // Тернарное выражение, возвращает большее число из x и y.

Тернарный оператор мы рассмотрим поподробнее чуть позже.

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

  • число
    Целое число, значение с плавающей точкой или символ (то есть любой примитивный тип, кроме boolean).
  • целое число
    Значения: byte, short, int, long или char (значения long не допускаются в операторе доступа к массиву []).
  • ссылка
    Объект или массив.
  • переменная
    Переменная или любая другая величина (например, элемент массива), которой
    можно присвоить значение.

Возвращаемый тип

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

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

Побочные эффекты

Каждый оператор вычисляет значение на основе одного или нескольких операндов. Однако некоторые операторы, в дополнение к основному вычислению, приводят к побочным эффектам. Если выражение подразумевает побочные эффекты, то при его вычислении состояние Java программы изменяется настолько, что повторное вычисление выражения может привести к результату, отличному от первого. Например, оператор инкремента ++ имеет побочный эффект приращения переменной. Выражение ++a увеличивает значение переменной a и возвращает новое, увеличенное значение. При следующем вычислении этого выражения получится уже другое значение. Различные операторы присваивания также имеют побочные эффекты. Например, выражение a*=2 можно записать в виде a=a*2. Значением выражения является значение a, умноженное на 2, но выражение имеет побочный эффект сохранения нового значения в a. Оператор вызова метода ()  имеет побочные эффекты, если побочные эффекты есть у вызываемого метода. Некоторые методы, например Math.sqrt(), просто вычисляют и возвращают значение без каких-либо побочных эффектов. Однако обычно методы всетаки имеют побочные эффекты. И наконец, оператор new имеет существенный побочный эффект, выраженный в создании нового объекта.

Порядок вычислений

Вычисляя выражение, интерпретатор Java выполняет различные операции в последовательности, заданной круглыми скобоками, а также приоритетом и ассоциативностью операторов. Однако перед началом операции интерпретатор вычисляет операнды оператора (исключение составляют операторы &&, ||  и ?:, которые не всегда вычисляют все свои операнды). Интерпретатор всегда вычисляет операнды слева направо. Это имеет значение, если какойлибо из операндов является выражением с побочными эффектами. В качестве примера рассмотрим следующий код:

int

a = 2;
int v = ++a + ++a * ++a;

Хотя умножение выполняется перед сложением, первыми вычисляются операнды оператора ++. Таким образом, выражение равно 3+4*5, или 23.

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

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

Поскольку большинство программ работает, в первую очередь, с числами, наиболее часто используются операторы, выполняющие арифметические операции. Арифметические операторы можно задавать с целыми числами, числами с плавающей точкой и даже с символами (то есть их можно применять с любым примитивным типом данных, кроме boolean). Арифметические операции с плавающей точкой применяются, если один из операндов является числом с плавающей точкой; в противном случае задействуется целочисленная арифметика. Это важно, так как арифметика для чисел с плавающей точкой отличается от целочисленной арифметики – например, по способу деления и способу обработки переполнения и округления. Существуют следующие арифметические операторы:

Сложение (+)

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

System

.out.println(«Total: » + 3 + 4); // Отображает «Total: 34», не 7!

 

Вычитание (−)

Если оператор является бинарным, то он вычитает второй операнд из первого. Например, 7−3 равняется 4. Оператор «» может выполнять унарную инверсию.

Умножение (*)

Оператор * умножает два числа. Например, 7*3 равняется 21.

Деление (/)

Оператор / делит первый операнд на второй. Деление целого числа на целое число дает целое число, а возможный остаток теряется. Однако если один из операндов является числом с плавающей точкой, то в результате деления получается число с плавающей точкой. Для целых чисел деление на нуль генерирует исключение ArithmeticException. В то же время при вычислениях, вовлекающих числа с плавающей точкой, деление на нуль просто дает бесконечность либо NaN:

7/3       // Равно 2
7/3.0f   // Равно 2.333333f
7/0       // Генерируется ArithmeticException
7/0.0    // Равно плюс бесконечности
0.0/0.0 // Равно NaN

Деление по модулю (%)

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

Оператор % вычисляет первый операнд по модулю второго (то есть он возвращает целый остаток от деления первого операнда на второй). Например, 7%3 дает 1. Знак результата совпадает со знаком первого операнда. Хотя оператор взятия по модулю обычно используют с целыми числами, он также подходит для значений с плавающей точкой. Например, 4.3%2.1 равняется 0.1. Вычисление значений по модулю нуль для целых чисел приводит к ArithmeticException. Для значений с плавающей точкой любое значение по модулю 0.0 и бесконечность по любому модулю дают NaN.

Унарный минус (−)

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

Оператор сцепления строк

Кроме сложения чисел, оператор + и родственный оператор += могут сцеплять, или соединять, строки. Если один из складываемых операндов является строкой, оператор преобразовывает другой операнд в строку. Например:

// Отображает «Quotient: 2.3333333»

System.out.println(«Quotient: » + 7/3.0f);

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

В интерпретатор Java встроены строковые преобразования для всех примитивных типов данных. Объект можно преобразовать в строку посредством метода toString(). В некоторых классах определены специальные методы toString(), чтобы с их помощью легко преобразовывать объекты данного класса в строки. Массив преобразуется в строку при вызове встроенного метода toString() , который, к сожалению, не возвращает удобное строковое представление содержимого массива.

Операторы инкремента и декремента

Оператор ++ увеличивает на единицу операнд, который является переменной, элементом массива или полем объекта. Поведение данного оператора зависит от его положения относительно операнда. Если оператор находится перед операндом, то он называется оператором префиксной формы инкремента (preincrement). Он увеличивает значение операнда на единицу и возвращает вычисленное значение. Если же оператор находится после операнда, то он называется оператором постфиксной формы инкремента (postincrement). Такой оператор увеличивает значение операнда на единицу, но возвращает значение операнда до увеличения.

Например, в следующем коде обе величины i и j  получают значение 2:

i = 1;
j = ++i;

Однако в следующем примере i получает значение 2, a j  – значение 1:

i = 1;
j = i++;

Аналогично, оператор –– уменьшает на единицу числовой операнд, который является переменной, элементом массива или полем объекта. Как и в случае оператора ++, поведение оператора –– зависит от его положения относительно операнда. Находясь перед операндом, он уменьшает значение операнда на единицу и возвращает полученное значение. Находясь после операнда, он уменьшает значение операнда на единицу, но возвращает первоначальное значение.

Выражения x++ и x— эквивалентны выражениям x=x+1 и x=x-1  соответственно; x вычисляется один раз, за исключением случаев использования операторов инкремента и декремента. Если x является выражением с побочными эффектами, это существенно меняет дело. Например, следующие два выражения не идентичны:

a[ i++]++;  // Увеличивает элемент массива
a
[ i++] = a[ i++] + 1; // Прибавляет единицу к одному элементу массива, а сохраняет его в другом

Чаще всего эти операторы – как в префиксной, так и в постфиксной форме – применяются для увеличения и уменьшения значения счетчика цикла.

Операторы сравнения и булевы операторы мы подробно рассмотрели с примитивным типом boolean тут. А побитовые операторы и операторы побитового сдвига рассмотрели с целочисленными типами тут.

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

Операторы присваивания сохраняют, или присваивают, значение какой-либо переменной. Левый операнд должен быть локальной переменной, элементом массива или полем объекта. Справа может находиться любое значение типа, совместимого с переменной. В отличие от всех остальных операторов, операторы присваивания обратно ассоциативны, то есть присваивания в a=b=c выполняются справа налево: a=(b=c) .

Условный оператор

Условный оператор ?:  является тернарным (три операнда) оператором, унаследованным из языка С. Он позволяет внедрять условие в само выражение. Его можно представить как версию оператора if/else. Знак вопроса (?) разделяет первый и второй операнды условного оператора, а двоеточие (:) – второй и третий. Первый операнд должен иметь boolean значение. Второй и третий операнды могут быть любого типа, но они должны приводиться к одному и тому же типу. Вначале условный оператор вычисляет первый операнд. Если он истинен, оператор вычисляет второй операнд, а результат представляет как значение выражения. В противном случае, если первый операнд ложен, условный оператор вычисляет и возвращает третий операнд. Условный оператор никогда не вычисляет оба операнда (второй и третий), поэтому следует осторожно использовать выражения с побочными эффектами. Ниже приведены примеры оператора:

int

max = (x > y) ? x : y;
String name = (name != null) ? name : «unknown»;

Примечание: приоритет оператора ?  ниже, чем всех других операторов, кроме операторов присваивания. Таким образом, операнды этого оператора обычно не нужно заключать в круглые скобки. Однако большинству программистов легче читать условные выражения, когда первый операнд заключен в круглые скобки – особенно если учесть, что и в условном операторе if условное выражение всегда заключено в круглые скобки.

Оператор instanceof

Этот оператор более подробно рассмотрим уже при изучении классов и объектов, а пока мотаем на ус. Хотя что-то возможно кому-то и не будет понятно.

Для оператора instanceof левым операндом должно быть значение объекта или массива, а правым операндом – имя ссылочного типа. Он возвращает true, если объект или массив является экземпляром указанного типа, иначе возвращается false. Оператор instanceof всегда возвращает false, если левый операнд является null. Если выражение instanceof равно true, можно без риска присваивать левый операнд переменной типа правого операнда.

Оператор instanceof можно использовать только с типами и значениями массивов и объектов, а не с примитивными типами и значениями.

Ниже приведены примеры использования instanceof (не все из них можно скомпилировать, это просто примеры для понимания):

«string»

instanceof String // Истинно: все строки являются экземплярами String
«» instanceof Object       // Истинно: строки также являются экземплярами Object
null instanceof String     // Ложно: null не является чьим>либо экземпляром

Object o =

new int[] {1,2,3};
o instanceof int[]    // Истинно: значение массива является int>массивом
o instanceof byte[] // Ложно: значение массива не является byte>массивом
o instanceof Object // Истинно: все массивы являются экземплярами Object // Используйте instanceof, чтобы убедиться в безопасности приведения объекта
if ( object instanceof Point) {
Point p = (Point) object;
}

Специальные операторы

В Java определены 5 языковых конструкций, которые иногда считаются операторами, а иногда – просто частью основного синтаксиса языка. Эти операторы перечислены в таблице приоритетов операторов, чтобы показать их приоритет по отношению к другим операторам. Далее эти языковые конструкции будут описаны более подробно. Здесь они изложены вкратце (так как многое мы еще пока не изучили), чтобы вы могли распознать их в примерах кода:

Доступ к члену объекта (.)

Объектом (object) называется множество данных и методы, работающие с этими данными, а поля данных и методы объекта являются его членами (members). Оператор точка (.) обеспечивает доступ к этим членам. Если о – это выражение, представляющее собой объектную ссылку, а f является именем поля объекта, то о.f равно значению данного поля. Если m – имя метода, то o.m относится к этому методу и позволяет вызывать его при помощи оператора (), описанного ниже.

Доступ к элементу массива ([])

Массивом (array) называется нумерованный список значений. Можно обратиться к каждому элементу массива через его номер, или индекс. Оператор [] позволяет обращаться к отдельным элементам массива. Если b является массивом, а i – выражением с типом int, то выражение b[i]  ссылается на один из элементов b. В отличие от других операторов, работающих с целыми значениями, данный оператор ограничивает типы значения индекса до int и более узких.

Вызов метода (())

Метод (method) представляет собой именованный фрагмент Java кода, который можно запускать, или вызывать, сопровождая имя метода несколькими выражениями, заключенными в круглые скобки и разделенными запятыми (выражений может и не быть). Значения этих выражений являются аргументами метода. Метод обрабатывает аргументы и может возвращать значение, которое становится значением выражения вызова метода. Если o.m является методом, не ожидающим аргументов, то его можно вызвать при помощи o.m(). Например, если метод требует наличия трех аргументов, то его можно вызвать выражением o.m(x,y,z). Перед вызовом метода интерпретатор Java вычисляет каждый передаваемый методу аргумент. Эти выражения обязательно вычисляются слева направо, что имеет значение только в случае побочных эффектов какоголибо из аргументов.

Создание объекта (new)

В Java объекты (и массивы) создаются при помощи оператора new, за которым следует тип создаваемого объекта и заключенный в круглые скобки список аргументов, передаваемый конструктору объектов. Конструктором называется особыйметод, который инициализирует вновь созданный объект. Таким образом, синтаксис создания объекта похож на синтаксис вызова метода. Например:

new

ArrayList();
new Point(1,2);

Преобразование или приведение типа (())

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

(

byte) 28 // Целый литерал приводится к типу byte
(int) (x + 3.14f) // Значение суммы с плавающей точкой приводится к целому
(String) h.get(k) // Базовый объект приводится к более узкому типу

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

Ну и на последок небольшой примерчик, чтобы не было скучно:

Немного объясню что делает данная программа.

До строки 15 все просто, даже объяснять не надо.

В 15 строке проверяется если есть аргументы командной строки, то строковой переменной isArgs задается значение переменной sYes, если нет аргументов, то переменной sNo.

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

 

Ну и теперь пример работы этой программы в консоли:

Стрелочками указаны два запуска данной прогарммы: без аргументов в командной строке и с ними.

Результат, как говорится, на лицо.

pr0java.blogspot.com

Что делает оператор ^ в Java? — java

Оператор ^ в Java

^ в Java — это эксклюзивный или ( «xor» ) оператор.

Возьмем 5^6 в качестве примера:

(decimal)    (binary)
     5     =  101
     6     =  110
------------------ xor
     3     =  011

Это таблица истинности побитового (JLS 15.22.1) и логическая (JLS 15.22.2) xor:

^ | 0 1      ^ | F T
--+-----     --+-----
0 | 0 1      F | F T
1 | 1 0      T | T F

Проще говоря, вы также можете думать о xor как о «том или ином, но не обоим!».

См. также


Экспоненциальность в Java

Что касается целочисленного возведения в степень, к сожалению, Java не имеет такого оператора. Вы можете использовать double Math.pow(double, double) (при необходимости приведя результат к int).


Вы также можете использовать традиционный бит-сдвигающий трюк для вычисления нескольких степеней из двух. То есть, (1L << k) равно двум для k-й степени для k=0..63.

См. также


Объединить примечание: этот ответ был объединен с другим вопросом, в котором было намерение использовать экспоненцию для преобразования строки "8675309" в int без использования Integer.parseInt в качестве упражнения по программированию (^ обозначает теперь возведение в степень). Целью OP было вычислить 8*10^6 + 6*10^5 + 7*10^4 + 5*10^3 + 3*10^2 + 0*10^1 + 9*10^0 = 8675309; в следующей части этого ответа указывается, что для этой задачи не требуется возведение в степень.

Схема Хорнера

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

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

8675309 = 8*10^6 + 6*10^5 + 7*10^4 + 5*10^3 + 3*10^2 + 0*10^1 + 9*10^0
        = (((((8*10 + 6)*10 + 7)*10 + 5)*10 + 3)*10 + 0)*10 + 9

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

В виде таблицы:

step   result  digit  result*10+digit
   1   init=0      8                8
   2        8      6               86
   3       86      7              867
   4      867      5             8675
   5     8675      3            86753
   6    86753      0           867530
   7   867530      9          8675309=final

qaru.site

Операторы if, else, switch в Java

Мы уже научили нашу игру задавать вопрос пользователю. Теперь нам нужно «поймать» его ответ, то есть узнать по какой кнопке он нажал. Определить верный или неверный ответ он дал. И на основании этого выбрать дальнейшие подходящие действия. Но для этого у нас пока недостаточно знаний и придётся их подтянуть.

Нам предстоит изучить еще несколько операторов. Мы уже умеем складывать (+), вычитать (-), умножать (*), делить (/), присваивать (=), инкрементировать (++), декрементировать (—). Познакомимся с еще некоторыми:

  • == — Оператор сравнения. Это проверка на равенство и выявление истинности или же ложности выражения. Выражение (10 == 9), например, ложно (false).
  • ! – Логический оператор НЕ. Выражение (!(2+2==5)) – правдиво (true), так как 2+2 НЕ РАВНО
  • != — Еще один оператор сравнения, проверяет НЕРАВЕНСТВО. Например, выражение (10 != 9) – правдиво (true), так как 10 не равно 9.
  • > — И еще оператор сравнения, проверяет БОЛЬШЕ ли одна часть выражения другой. (10 > 9) – правдиво (true).
  • < — Оператор сравнения МЕНЬШЕ. Проверяет меньше ли значение выражения стоящее слева от значения выражения, находящегося справа. (10 < 9) – ложно (false).
  • >= — Оператор сравнения БОЛЬШЕ ИЛИ РАВНО. Этот оператор проверяет, является ли одно значение больше или равно другому и если является, то выражению присваивается true. К примеру, выражение (10 >=9) правдиво (true), (10 >=10) тоже правдиво (true).
  • <= — Как и предыдущий оператор, это проверяет на совпадение двух условий сразу, только на этот раз МЕНЬШЕ ИЛИ РАВНО. (10 <= 9) – ложь (false), (10 <=10) – правда (true).
  • && — Этот оператор известен как логическое И. Он проверяет две или более части выражения, и все части должны быть истинными, чтобы общий результат был истинным (true). Логическое И обычно используется совместно с другими операторами для построения более сложных проверок. Выражение ((10 > 9) && (10 < 11)) – правдиво (true), так как обе части выражения истинны(true). А выражение ((10 > 9) && (10 < 9)) – ложно (false), так как только одна часть общего выражения правдива, а другая ложная.
  • || — Этот оператор называется логическое ИЛИ. Он аналогичен логическому оператору И, за исключением того, что только одна часть общего выражения должна быть правдива, чтобы общее выражение было истинно (true). Выражение ((10 > 9) || (10 < 9)) истинно (true), так как по крайней мере одна из его частей истинна (true).

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

Решение 1. Если они перешли через мост, застрелить их. Ключевое слово if.

Немного теории о том, как мы можем использовать те операторы, о которых шла речь выше. Давайте сделаем предыдущие примеры менее абстрактными используя одно из множества ключевых слов языка Java – “if” и какую-нибудь интересную ситуацию. Представьте, что генерал армии погибает в бою и нету никого настолько же опытного, как он, чтобы отдавать приказы армии. И тут-то генералу приходит хорошая мысль в голову, он решает написать программу на Java и тем самым передать последние приказы своим подчинённым. Солдаты должны держать одну сторону моста в ожидании подкрепления. И первой командой генерал хочет убедиться понимают ли его солдаты: Если враги перешли мост – застрелите их. Давайте обыграем эту ситуацию на языке Java. Нам нужна переменная типа BooleanisComingOverBridge. В следующем кусочке кода предполагается, что такая переменная уже была объявлена и инициализирована:

if(isComingOverBridge){
        //Застрелить врага
        }

Если переменная isComingOverBridge принимает значение “true”, то будет выполнен код между открывающейся и закрывающейся фигурными скобками. Если переменная isComingOverBridge принимает значение “false”, то программа будет выполнять код, который будет написан после блока if.

Решение 2. Иначе, сделать это. Ключевое слово else.

Генерал также хочет сказать своим солдатам, что делать в случае если враг не переходит через мост. Представляем вам еще одно ключевое слово – else”. Генерал с помощью else” даёт команду своим солдатам держать позицию, в случае если враг не переходит мост:

        if(isComingOverBridge){
//Застрелить врага
                }else{
//Держать позиции
                }

Затем генерал понимает, что проблема не так проста, как ему показалось сначала. Что если враг переходит мост и его войска превосходят количеством войска нашего генерала. Таким образом он приходит к следующему выводу:

    boolean isComingOverTheBridge;
    int enemyTroops;
    int friendlyTroops;
//Объявили переменные
//Переход if
        if(isComingOverTheBridge && friendlyTroops > enemyTroops){
//застрелить врага
        }else if(isComingOverTheBridge && friendlyTroops < enemyTroops) {
//взорвать мост
        }else{
//держать позиции
        }

Наконец, последняя забота генерала заключалась в том, что если враг перейдет через мост, размахивая белым флагом капитуляции, и будет немедленно убит, то его люди окажутся военными преступниками. Введя еще одну переменную типа Boolean – wavingWhiteFlag, он написал следующий код:

if (wavingWhiteFlag){
//Взять в плен
        }

Но куда поместить этот код ему было непонятно. Поразмыслив, генерал решил использовать оператор “логическое НЕ (!)” следующим образом:

if (!wavingWhiteFlag){//если НЕ сдаются, заходим в цикл
        if(isComingOverTheBridge && friendlyTroops > enemyTroops){
//застрелить врага
        }else if(isComingOverTheBridge && friendlyTroops < enemyTroops) {
//взорвать мост
        }
        }else{//этот else для нашего первого if
//взять в плен
        {
//держать позиции

Тут демонстрируется, что мы можем вкладывать if” “else” друг в друга, чтобы создавать различные решения.

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

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

Оператор Switch.

Мы видели огромные и практически безграничные возможности Java по комбинированию операторов с помощью условных переходов if” иelse”. Но иногда решение в Java может быть сделано и по-другому.

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

Switch” начинается так:

switch(argument){
        }

Здесь в качестве аргумента должна находится какая-либо переменная или же выражение. Затем в фигурных скобках мы можем принимать решения на основе аргумента case и break элементов:

case x:
//код для x
break;
case y:
//код для y
break;

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

Так же присутствует возможность использовать ключевое слово default на случай если ни один из case не был достигнут (аргумент из switch не подошел ни к одному из case). К примеру:

default://никакого значения сюда не передаём
//сделать что-нибудь здесь, так как ни один из case не сработал
        break;

Предположим, мы пишем старомодную игру, где игрок выбирает команды, такие как «идти на восток», «идти на запад», «взять меч», и так далее. В этом случае switch может обрабатывать такую ситуацию, как этот пример кода, и мы можем использовать default для обработки случая, когда игрок вводит команду, которая не предназначена для обработки:

//обрабатываем ввод от пользователя в String-переменную с именем command
        switch(command){
                case "Go East":
//код для похода на восток
                break;
                case "Go West":
//код для похода на запад
                break;
                case "Take sword":
//код для взятия меча
                break;
//можно добавлять еще case
                default:
//Извините, но я не понимаю, что мне нужно сделать
                break;
        }

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

На этом пока наша теория заканчивается. В следующем уроке мы применим приобретённые знания (в частности switch-переход) для того, чтобы наш метод onClick обрабатывал нажатия по кнопкам.

android-study.ru