Собеседование по java
Содержание:
- Примеры простых тернарных операторов
- Синтаксис оператора switch
- Объекты
- Дата и Время
- Приоритет операторов в Java
- Java: что за зверь?
- Целые типы
- Арифметические операции
- JSON
- Что такое лямбда-выражения
- Битовая операция ИЛИ
- Оператор switch
- Битовая операция НЕ
- Похожие языки
- Побитовые (поразрядные) операции
- Логическое И (&&)
- Пример 2: Арифметические операторы
- Заявление break
- Пример 3
- Методы класса
- Обновлённый оператор switch в Java 14
Примеры простых тернарных операторов
Одним из применений тернарного оператора в Java является назначение минимального (или максимального) значения двух переменных третьей переменной, по существу заменяя вызов метода Math.min (a, b) или Math.max (a, b).
Вот пример, который присваивает минимуму из двух переменных, a и b, третьей переменной с именем minVal:
minVal = (a< b) ? a : b.
В этом коде, если переменная a меньше, чем b, minVal присваивается значение a; в противном случае minVal присваивается значение b.
Я думаю, что круглые скобки делают код немного легче для чтения, но опять же, они не являются обязательными, поэтому используйте любой синтаксис, который вы предпочитаете.
Вы можете использовать аналогичный подход, чтобы получить абсолютное значение числа, используя такой код:
int absValue = (a<0)? -а: а.
Первый операнд в тройном операторе должен быть логическим или оператором с логическим результатом. Если первый операнд равен true, то оператор возвращает второй операнд, иначе он возвращает третий операнд.
Синтаксис оператора switch
switch (variable/expression) { case value1: // statements of case1 break; case value2: // statements of case2 break; .. .. ... .. .. ... default: // default statements }
Оператор switch оценивает выражение (в основном переменное) и сравнивает его со значениями (могут быть выражениями) каждой метки case.
Теперь, если значение соответствует определенной метке case, то выполняются все операторы соответствующей метки case.
Например, если переменная / выражение равно значению 2. В этом случае выполняются все операторы этого совпадающего case (операторы case2).
Это важно, потому что если break не используется, все операторы после соответствующего case выполняются последовательно до конца оператора switch. Что следует помнить:
Что следует помнить:
- Для выражения переключения может быть одно или N значений case.
- Значение case должно быть только типа выражения переключения. Значение case должно быть буквальным или постоянным. Он не допускает переменных.
- Значения case должны быть уникальными. В случае повторяющегося значения он отображает ошибку времени компиляции.
- Выражение переключателя Java должно быть byte, short, int, long, перечислением и строкой.
- Каждый оператор case может иметь оператор break, который не является обязательным.
- Когда элемент управления достигает оператора break, он переходит к элементу управления после выражения switch.
- Также case может иметь метку по умолчанию, которая является необязательной.
Объекты
Объекты в Java работают по тому же принципу, что и все объекты в ООП: можно создавать сколько угодно объектов на основе классов и делать их любой сложности.
Обычно используют классы, прописанные в том же файле, что и программа. Если нужно использовать класс из другой программы, её подключают отдельно. Вот самый простой способ сделать объект на основе предыдущего класса с заказом:
Текст:
Михаил Полянин
Редактура:
Максим Ильяхов
Художник:
Даня Берковский
Корректор:
Ирина Михеева
Вёрстка:
Мария Дронова
Соцсети:
Олег Вешкурцев
Дата и Время
System.currentTimeMillis или System.nanoTime?
В Java есть два стандартных способа проведения операций со временем, и не всегда ясно, какой из них следует выбрать.
Метод возвращает текущее количество миллисекунд с начала эры Unix в формате Long. Его точность составляет от 1 до 15 тысячных долей секунды в зависимости от системы.
Метод имеет точность до одной миллионной секунды (наносекунды) и возвращает текущее значение наиболее точного доступного системного таймера.
Таким образом, метод лучше применять для отображения и синхронизации абсолютного времени, а для измерения относительных интервалов времени.
Валидация Даты из строки
Если необходимо достать объект из обычной строки в Java, можете использовать небольшой утилитный класс, который приведен ниже. Он позаботится обо всех сложностях валидации и преобразовании строки в объект .
Пример его использования:
Результат:
Приоритет операторов в Java
Приоритет операторов определяет группирование терминов в выражении. Это влияет как вычисляется выражение. Некоторые операторы имеют более высокий приоритет, чем другие; например оператор умножения имеет более высокий приоритет, чем оператор сложения:
Например, x = 7 + 3 * 2. Здесь x присваивается значение 13, не 20, потому что оператор «*» имеет более высокий приоритет, чем «+», так что сначала перемножается «3 * 2», а затем добавляется «7».
В таблице операторы с наивысшим приоритетом размещаются в верхней части, и уровень приоритета снижается к нижней части таблицы. В выражении высокий приоритет операторов в Java будет оцениваться слева направо.
Java: что за зверь?
Java — мультифункциональный объектно-ориентированный язык со строгой типизацией.
Что это значит?
С мультифункциональностью всё достаточно просто: Java действительно почти «волшебная таблетка» — на ней можно разрабатывать десктопные приложения, приложения под Android, заниматься веб-разработкой… Подробнее об этом ниже.
Строгая (сильная) типизация не позволяет смешивать в выражениях разные типы и не выполняет автоматически неявные преобразования. Это добавляет мороки: какие-то части приходится прописывать самому, а свободы у вас меньше, — зато в обмен на это вы получаете надёжность.
Объектно-ориентированный язык — это язык, созданный по модели объектно-ориентированного программирования. В ней существуют классы и объекты. Классы — это типы данных, а объекты — представители классов. Вы создаёте их сами, даёте названия и присваиваете им свойства и операции, которые с ними можно выполнять. Это как конструктор, который позволяет построить то, что вы хотите. Именно с помощью этой системы объектов в основном программируют на Java.
Целые типы
В языке Java аж 4 целых типа: , , и . Они отличаются размером и диапазоном значений, которые могут хранить.
Тип
Самым часто используемым является тип . Его название происходит от Integer (целый). Все целочисленные литералы в коде имеют тип (если в конце числа не указана буква , или ).
Переменные этого типа могут принимать значение от до .
Это достаточно много и хватает почти для всех случаев жизни. Почти все функции, которые возвращают число, возвращают число типа .
Примеры:
Код | Пояснение |
---|---|
Метод возвращает длину строки | |
Поле содержит длину массива. |
Тип
Тип получил свое название от . Его еще называют короткое целое. В отличие от типа , его длина всего два байта и возможный диапазон значений от до .
То есть в нем даже число миллион не сохранишь. Даже 50 тысяч. Это самый редко используемый целочисленный тип в Java. В основном его используют, когда хотят сэкономить на памяти.
Допустим, у вас ситуация, когда заранее известно, что значения с которыми вы работаете не превышает 30 тысяч, и таких значений миллионы.
Например, вы пишете приложение, которое обрабатывает картинки сверхвысокой четкости: на один цвет приходится бит. А точек у вас в картинке — миллион. И вот тут уже играет роль, используете вы тип или .
Тип
Этот тип получил свое название от — его еще называют длинное целое. В отличие от типа , у него просто гигантский диапазон значений: от до
Почему же он не является основным целым типом?
Все дело в том, что Java появилась еще в середине 90-х, когда большинство компьютеров были 32-х разрядными. А это значило, что все процессоры были заточены под работу с числами из 32-х бит. С целыми числами из 64-х бит процессоры работать уже умели, но операции с ними были медленнее.
Поэтому программисты разумно решили сделать стандартным целым типом тип , ну а тип использовать только тогда, когда без него действительно не обойтись.
Тип
Это самый маленький целочисленный тип в Java, но далеко не самый редко используемый. Его название совпадает со словом — минимальная адресуемая ячейка памяти в Java.
Размер допустимых значений типа не так уж велик: от до . Но не в этом его сила. Тип чаще всего используется, когда нужно хранить в памяти большой блок обезличенных данных. Массив типа просто идеально подходит для этих целей.
Например, вам нужно куда-то скопировать файл.
Вам не нужно обрабатывать содержимое файла: вы просто хотите создать область памяти (буфер), скопировать в нее содержимое файла, а затем записать эти данные из буфера в другой файл. Массив типа — то, что нужно для этих целей.
Тем более, что в переменной-типа-массив хранится только ссылка на область памяти. При передаче значения этой переменной в какой-то метод произойдет только передача адреса в памяти, а сам блок памяти копироваться на будет.
Арифметические операции
Арифметические операции позволяют выполнять сложение (операция «+»), вычитание (операция «-»), умножение (операция «*»), деление (операция «/») и взятие остатка (операция «%»). Эти операции имеют такие же приоритеты, что и в обычной математике, которую изучают в школе, то есть умножение и деление выполняется перед сложением и вычитанием.
Java
double x1 = 1.1 + 2.3; // 3.4
double x2 = 1.1 — 0.1; // 1.0
double x3 = 1.1 * 2 + 1; // 3.2
double x4 = 6 / 2.0; // 3.0
int x5 = 12 + 3; // 15
int x6 = 13 % 5; // 3
1 |
doublex1=1.1+2.3;// 3.4 doublex2=1.1-0.1;// 1.0 doublex3=1.1*2+1;// 3.2 doublex4=62.0;// 3.0 intx5=12+3;// 15 intx6=13%5;// 3 |
При выполнении арифметических операций операнды всегда преобразуются как минимум в
int (например при умножении двух переменных типа
byte оба значения сначала преобразуются в
int, и результат выражения будет
int).
При выполнении арифметической операции над операндами разных типов результат операции будет иметь наибольший тип, Что можно описать следующими правилами:
- Если один из операндов имеет тип
double, то результат выражения имеет тип
double, иначе смотри пункт 2. - Если один из операндов имеет тип
float, то результат выражения имеет тип
float, иначе смотри пункт 3. - Если один из операндов имеет тип
long, то результат выражения имеет тип
long, иначе результат выражения имеет тип
int.
(например, при сложении
int и
long результат будет иметь тип
long, а при сложении
long и
float результат будет иметь тип
float, а при сложении
float и
double результат будет иметь тип
double).
Если результат операции с целочисленными данными выходит за диапазон, то старшие биты отбрасываются, и результирующее значение будет совершенно неверным. При попытке деления на 0 возникает исключение
java.lang.ArithmeticExceptionzero.
При выполнении операций с плавающей точкой при выходе за верхнюю или нижнюю границу диапазона получается
+Infinity (
Double.POSITIVE_INFINITY и
Float.POSITIVE_INFINITY) и
-Infinity (
Double.NEGATIVE_INFINITY и
Float.NEGATIVE_INFINITY ) соответственно, а при получении слишком маленького числа, которое не может быть нормально сохранено в этом типе данных получается -0.0 или +0.0.
При выполнении операций с плавающей точкой результат
NaN (
Double.NaN и
Float.NaN) получается в следующих случаях:
- Когда один из операндов
- В неопределённых результатах:
- Деления 0/0, ∞/∞, ∞/−∞, −∞/∞, −∞/−∞
- Умножения 0×∞ and 0×−∞
- Степень 1∞
- сложения ∞ + (−∞), (−∞) + ∞ и эквивалентные вычитания.
- Операции с комплексными результатами:
- Квадратный корень из отрицательного числа
- Логарифм отрицательного числа
- Тангенс 90 градусов и ему подобных (или π/2 радиан)
- Обратный синус и косинус от числа меньше −1 и больше +1.
JSON
Сериализация и Десериализация
JSON — невероятно удобный и полезный синтаксис для хранения и обмена данными. Java полностью поддерживает это.
Прим. перев. Для использования JSON из примера необходимо подключить библиотеку JSON Simple.
Вы можете сериализовать данные следующим образом:
Получается следующая строка JSON:
Десериализация в Java выглядит так:
Используемый в примере файл JSON (jsonDemoFile.json):
Прим. перев. В Java проектах очень часто для работы с JSON используют библиотеки Gson от Google или Jackson. Обе библиотеки очень популярны и хорошо поддерживаются. Попробуйте и их.
Что такое лямбда-выражения
Это компактный синтаксис, заимствованный из λ-исчисления, для передачи кода в качестве параметра в другой код.
По сути, это анонимный (без имени) класс или метод. Так как всё в Java (за исключением примитивных типов) — это объекты, лямбды тоже должны быть связаны с конкретным объектным типом. Как вы догадались, он называется функциональным интерфейсом.
То есть лямбда-выражение не выполняется само по себе, а нужно для реализации метода, который определён в функциональном интерфейсе.
Не будь лямбд, вызывать метод processTwoNumbers каждый раз приходилось бы так:
Примечание. biFunction в примере создана с использованием анонимных классов. Без этого нам пришлось бы создавать класс, реализующий интерфейс ToIntBiFunction, и объявлять в этом классе метод applyAsInt. А с анонимным классом мы всё это сделали на лету.
В примере выше всё, кроме одной строчки, избыточно. За содержательную часть (логику работы) отвечает только одно выражение return a + b, а всё остальное — техническая шелуха. И её пришлось написать многовато, даже чтобы просто передать методу код сложения двух чисел.
Здесь и вступают в игру лямбды. С ними можно сократить создание biFunction всего до десяти символов!
Лямбда строится так: (параметры) -> (код метода)
А наша лямбда будет такой:
ToIntBiFunction<Integer, Integer> biFunction = (a, b) -> a + b;
И всё! Этот блок из 10 символов можно передавать как аргумент методу, ожидающему функциональный интерфейс в качестве параметра. Причём чаще всего обходятся без промежуточной переменной — передают напрямую лямбду:
Компилятор проверит, что лямбда подходит функциональному интерфейсу — принимает нужное число параметров нужного типа. Напомню, в нашем примере задействован функциональный интерфейс ToIntBiFunction. Сигнатура его единственного абстрактного метода содержит два параметра (Integer a, Integer b).
Например, такой вот вызов метода не скомпилируется, потому что передан всего один параметр:
Лямбды записывают . Мы рассмотрели только один вариант.
Битовая операция ИЛИ
Следующая битовая операция – поразрядное ИЛИ. Она задается оператором | и
ее таблица истинности выглядит следующим образом.
x |
y |
ИЛИ |
1 |
1 |
|
1 |
1 |
|
1 |
1 |
1 |
Где обычно
используется эта операция? Обычно ее применяют, когда нужно включить отдельные
биты переменной. Рассмотрим такую программу.
byte flags = 8; //двоичный вид: 00001000 byte mask = 5; //двоичный вид: 00000101 flags = (byte)(flags | mask); //двоичная запись 00001101 (число 13) System.out.println(flags);
Здесь мы имеем
такую картину.
flags= |
1 |
||
mask= |
1 |
1 |
|
flags= |
1 |
1 |
1 |
то есть,
операция поразрядное ИЛИ, как бы собирает все единички из обеих переменных и
получается такое своеобразное сложение. Кстати, в этом случае действительно
получилось 8+5=13. Но это будет не всегда так, например, если
byte flags = 9; //двоичный вид: 00001001
то результат
тоже будет 13, так как операция ИЛИ включает бит вне зависимости был ли он уже
включен или нет, все равно на выходе будет единица. И здесь уже 9+5=13, что
математически неверно.
Оператор switch
Рассмотрим следующий кусок кода:
Java
if (mode == 0) {
// operators for mode 0
} else if (mode == 1) {
// operators for mode 1
} else if (mode == 2) {
// operators for mode 2
} else {
// operators for other mode.
}
1 |
if(mode==){ // operators for mode 0 }elseif(mode==1){ // operators for mode 1 }elseif(mode==2){ // operators for mode 2 }else{ // operators for other mode. } |
В куске кода, приведённом выше, проверяется значение переменной
mode. Для значений 0, 1 и 2 предусмотрены отдельные блоки кода, и ещё один блок кода предусмотрен для всех остальных значений. Оператор
switch делает то же самое, но делает код более наглядным:
Java
switch (mode) {
case 0:
// operators for mode 0
break;
case 1:
// operators for mode 1
break;
case 2:
// operators for mode 2
break;
default:
// operators for other mode
break;
}
1 |
switch(mode){ case // operators for mode 0 break; case1 // operators for mode 1 break; case2 // operators for mode 2 break; default // operators for other mode break; } |
Этот кусок кода с оператором
switch делает абсолютно то же самое, что и кусок кода с
if, рассмотренный до этого, но рекомендуется использовать вариант со
switch, так как он более нагляден.
Оператор
switch работает в следующем порядке:
- Вычисляется выражение в скобках (в данном примере оно состоит просто из переменной
mode ) - Полученное значение проверяется подряд со значениями в
case , и выполняется тот блок операторов, который относится к
case со значением, совпадающим со значением выражения. - Если ни одно из значений не совпало, то выполняется блок
default. - По ключевому слову
break выполнение блока внутри
case или
default завершается и управление передаётся на следующую инструкцию за блоком
switch.
С помощью
if-then и
if-then-else можно проверять любые условия, но с помощью
switch можно проверять только значения выражений типа
byte ,
short ,
char ,
int , перечисления (будет описано позднее),
String (начиная с Java SE 7), а также классы
java.lang.Byte ,
java.lang.Short ,
java.langCharacter ,
java.lang.Integer. Проверяемые значения в
case обязательно должны быть константными литералами. Если значение выражения в
switch равно
null, то возникает
java.lang.NullPointerException. Нагляднее всего
switch выглядит именно с перечислениями.
Ключевое слово
break не обязательно. В случае его отсутствия по завершении выполнения блока операторов внутри одного
case выполняются операторы следующего за ним
case. Это позволяет использовать один блок операторов для нескольких значений
case:
Java
switch (mode) {
case -1:
System.out.println(«mode -1»);
break;
case 0:
System.out.println(«mode 0»);
case 1:
case 2:
System.out.println(«mode 0 or 1 or 2»);
break;
case 3:
System.out.println(«mode 2»);
break;
default:
System.out.println(«mode default»);
break;
}
1 |
switch(mode){ case-1 System.out.println(«mode -1»); break; case System.out.println(«mode 0»); case1 case2 System.out.println(«mode 0 or 1 or 2»); break; case3 System.out.println(«mode 2»); break; default System.out.println(«mode default»); break; } |
Если
mode равно 0, то код выше выведет в консоль:
mode 0
mode 0 or 1 or 2
1 |
mode 0 mode 0 or 1 or 2 |
Если
mode равно 1, то код выше выведет в консоль:
mode 0 or 1 or 2
1 | mode 0 or 1 or 2 |
Если
mode равно 2, то код выше выведет в консоль:
mode 0 or 1 or 2
1 | mode 0 or 1 or 2 |
Блок
default не обязательно указывать в конце блока
switch. Он может стоять и в начале, и в середине (но рекомендуется всегда писать его последним, так получается гораздо нагляднее, потому что он выполняется в том случае, если ни один из
case -ов не подошёл):
Java
switch (mode) {
case 0:
System.out.println(«mode 0»);
break;
default:
System.out.println(«mode default»);
break;
case 1:
System.out.println(«mode 1»);
break;
case 2:
System.out.println(«mode 2»);
break;
}
1 |
switch(mode){ case System.out.println(«mode 0»); break; default System.out.println(«mode default»); break; case1 System.out.println(«mode 1»); break; case2 System.out.println(«mode 2»); break; } |
Можно даже вообще не указывать блок
default:
Java
switch (mode) {
case 0:
System.out.println(«mode 0»);
break;
case 1:
System.out.println(«mode 1»);
break;
case 2:
System.out.println(«mode 2»);
break;
}
1 |
switch(mode){ case System.out.println(«mode 0»); break; case1 System.out.println(«mode 1»); break; case2 System.out.println(«mode 2»); break; } |
Битовая операция НЕ
Начнем с самой
простой битовой операции НЕ, которая выполняет инверсию бит в соответствии с
такой табличкой:
x |
НЕ |
1 |
|
1 |
На языке Java она
записывается как ~ тильда. И приведем такую программу.
int var = 121; //двоичный вид: 00000000 00000000 00000000 01111001 int not_v = ~var; //результат: 11111111 11111111 11111111 10000110 (число -122) System.out.println(not_v);
Здесь мы сначала
задаем переменную var со значением 121, затем, выполняем ее
побитовую инверсию, и выводим результат на экран.
Запустим
программу и видим на экране число -122, что и должно быть, так как инверсия
последних 7 бит дает
1111001 = 121+1
значит, это
число -122.
Похожие языки
Из близких родственников Java можно выделить популярный язык программирования С#. Близки они настолько, что некоторые школы, выпускают Java-программистов, которые впоследствии устраиваются на позицию C#-разработчика. И дело не только в подходе к обучению на подобных курсах, а в технических схожестях. И это неудивительно, потому что язык Microsoft создавался с оглядкой на Java.
Поэтому С# используется для решения тех же задач, для которых изначально создавался Java. В целом, можно даже считать их взаимозаменяемыми.
Java против Python
Главное преимущество Python – его простой синтаксис. Действительно, написать простой скрипт или опробовать новую идею в среде Python куда проще. Не нужно писать и компилировать целую программу, чтобы добиться результата.
Это проявляется при работе с любыми сущностями кода. Те же классы в Python и Java выглядят по-разному. В последнем они заметно массивнее и сложнее в понимании, чем те, что предлагает Python.
В отличие от Python, в Java используется строгая типизация, что вынуждает разработчиков быть дисциплинированными и всегда заранее декларировать используемый тип данных. В противном случае компилятор отзовется ошибкой. Python в этом плане менее придирчив.
А еще Python поддерживает больше вариантов оформления кода, поэтому большинство разработчиков считает, что его проще читать.
Java против C++
Несмотря на наличие общих черт между этими языками в части синтаксиса, у Java и C++ есть ряд значимых отличий.
К примеру, С++ использует только компилятор. То есть механизм, преобразующий весь код в объектную структуру, напрямую прочитываемую компьютером. Java же, помимо компилятора, задействует интерпретатор, читающий каждую строку и сразу выполняющий инструкции, в ней описанные.
С++ поддерживает перезагрузку операторов и перегрузку методов, а также такие типы, как struct и union. Из вышеперечисленного Java поддерживает только перегрузку методов.
С++ чаще используется для создания музыкального программного обеспечения, например секвенсоров или эмуляторов аналогового оборудования. Также С++ код можно обнаружить в компонентах операционных систем Windows и macOS.
Многие разработчики сравнивают С++ и Java в пользу второго, потому что он имеет схожие возможности, но не содержит в себе недостатков первого.
Побитовые (поразрядные) операции
В следующей таблице представлены побитовые операции применяемые в языке Java:
Операция
Описание
~
Поразрядная унарная операция НЕ (дополнение)
&
Поразрядная логическая операция И (AND, побитовая конъюнкция)
|
Поразрядная логическая операция ИЛИ (OR, побитовая дизъюнкция)
^
Поразрядная логическая операция исключающее ИЛИ (XOR)
Побитовые операторы применяются к целочисленным типам , , , , . Побитовые операторы применяются к каждому отдельному биту каждого операнда.
Результаты выполнения побитовых логических операций:
A |
B |
A | B |
A & B |
A ^ B |
~A |
1 |
|||||
1 |
1 |
1 |
|||
1 |
1 |
1 |
1 |
||
1 |
1 |
1 |
1 |
1.1. Побитовое ИЛИ (OR , |)
Результирующий бит, полученный в результате выполнения оператора OR, равен 1, если соответствующий бит в любом из операндов равен 1.
1.2. Побитовое И (AND , &)
Значение бита, полученное в результате выполнения побитового оператора AND, &, равно 1, если соответствующие биты в операндах также равны 1. Во всех остальных случаях значение результирующего бита равно 0.
1.3. Побитовое исключающее ИЛИ (XOR , ^)
Результирующий бит, полученный в результате выполнения оператора XOR, ^, равен 1, если соответствующий бит только в одном из операндов равен 1. Во всех других случаях результирующий бит равен 0.
1.4. Побитовое НЕ (NOT , ~)
Унарный оператор NOT (Не), ~, называемый также побитовым дополнением, инвертирует все биты операнда.
Рассмотрим теперь применение побитовых операций в программе. В следующем примере также показано применение метода , который приводит десятичное значение к двоичному:
Логическое И (&&)
Логический оператор И выполняет логическую операцию конъюнкции двух булевых значений. Конъюнкция – это сложное логическое выражение, которое считается истинным только в том случае, когда оба его операнда (выражения) являются истинными , во всех остальных случаях данное сложное выражение ложно .
Примеры:
Выполнить код »
Скрыть результаты
Часто оператор И используется совместно с двумя выражениями сравнения:
Выполнить код »
Скрыть результаты
Операторы сравнения, согласно , имеют более высокий приоритет, чем логические операторы и , поэтому приведенное выше выражение можно писать без скобок.
Для оператора не обязательно, чтобы его операнды бьли булевыми значениями. Он принимает любые значения, поскольку они могут быть преобразованы в булевы.
Например, в следующем примере число 1 будет воспринято как , а 0 – как :
Выполнить код »
Скрыть результаты
Логическое И начинает работу с вычисления левого операнда. Если получившееся значение может быть преобразовано в (например, , , , , или ), значит, результат выражения равен или непреобразованному значению левого выражения. Поэтому вычисление и преобразование второго операнда не выполняется. В противном случае, если значение слева является истинным, тогда результат всего выражения определяется значением справа. Поэтому, когда значение слева является истинным, оператор вычисляет и возвращает значение справа:
Выполнить код »
Скрыть результаты
Итак, оператор вычисляет операнды слева направо до первого ложного аргумента и возвращает его значение, а если все операнды истинные – то возвращается значение последнего. Если первый операнд – , то результат будет , и остальные значения игнорируются.
Такое поведение оператора , позволяющее экономить ресурсы и не вычислять правый аргумент, иногда называют «короткой схемой вычислений».
Это особенно заметно, когда выражения, имеющие побочные эффекты (присваивания, инкременты, декременты и вызовы функций), помещаются в правую часть оператора :
Выполнить код »
Скрыть результаты
При выполнении логического И в этом коде возникает ошибка, потому что переменная не объявлена. Значение левого операнда – , поэтому интерпретатор переходит к оценке правого операнда. Если изменить значение левого операнда на , ошибка не возникает:
Выполнить код »
Скрыть результаты
В этом примере переменная тоже не определена, но правый операнд никогда не оценивается, потому что левый операнд равен и, следовательно, результатом данного кода тоже может быть только . Используя оператор И , помните о так называемой «сокращенной схеме его вычисления».
Пример 2: Арифметические операторы
class ArithmeticOperator { public static void main(String[] args) { double number1 = 12.5, number2 = 3.5, result; // Используется оператор сложения result = number1 + number2; System.out.println("number1 + number2 = " + result); // Используется оператор вычитания result = number1 - number2; System.out.println("number1 - number2 = " + result); // Используется оператор умножения result = number1 * number2; System.out.println("number1 * number2 = " + result); // Используется оператор деления result = number1 / number2; System.out.println("number1 / number2 = " + result); // Используется оператор остатка result = number1 % number2; System.out.println("number1 % number2 = " + result); } }
Когда вы запустите программу, на экран выведется:
number1 + number2 = 16.0 number1 - number2 = 9.0 number1 * number2 = 43.75 number1 / number2 = 3.5714285714285716 number1 % number2 = 2.0
В примере с оператором деления Java, приведенном выше, использованные операнды – переменные. Кроме этого могут использоваться символьные значения. Например:
result = number1 + 5.2; result = 2.3 + 4.5; number2 = number1 -2.9;
Оператор «+» также может быть использован, чтобы соединить (конкатенировать) две строки или больше.
Заявление break
Хотя большинство операторов switch в реальной жизни подразумевают, что должен быть выполнен только один из блоков case, оператор break необходим для выхода из switch после завершения блока.
Чтобы продемонстрировать это, опустим операторы break и добавим вывод в консоль для каждого блока:
public String forgetBreakInSwitch(String animal) { switch (animal) { case "DOG": System.out.println("domestic animal"); default: System.out.println("unknown animal"); } }
Давайте выполним этот код ForgotBreakInSwitch(«DOG») и проверим вывод, чтобы убедиться, что все блоки выполняются:
Поэтому нам следует быть осторожными и добавлять операторы break в конце каждого блока, если нет необходимости переходить к коду под следующей меткой.
Единственный блок, в котором не требуется разрыв, — это последний, но добавление разрыва к последнему блоку делает код менее подверженным ошибкам.
Мы также можем воспользоваться этим поведением, чтобы опустить break, когда мы хотим, чтобы один и тот же код выполнялся для нескольких операторов case. Давайте перепишем пример из предыдущего раздела, сгруппировав первые 2 случая:
public String exampleOfSwitch(String animal) { String result; switch (animal) { case "DOG": case "CAT": result = "domestic animal"; break; case "TIGER": result = "wild animal"; break; default: result = "unknown animal"; break; } return result; }
Пример 3
Допустим, у нас есть следующие вложенные операторы if-else:
public String exampleOfIF(String animal) { String result; if (animal.equals("DOG") || animal.equals("CAT")) { result = "domestic animal"; } else if (animal.equals("TIGER")) { result = "wild animal"; } else { result = "unknown animal"; } return result; }
Приведенный выше код выглядит не очень хорошо, и его будет сложно поддерживать и обдумывать. Чтобы улучшить читаемость, мы могли бы использовать здесь оператор switch:
public String exampleOfSwitch(String animal) { String result; switch (animal) { case "DOG": result = "domestic animal"; break; case "CAT": result = "domestic animal"; break; case "TIGER": result = "wild animal"; break; default: result = "unknown animal"; break; } return result; }
Как показано выше, мы сравниваем animal аргумента switch с несколькими значениями case. Если ни одно из значений case не равно аргументу, то выполняется блок под меткой по умолчанию.
Проще говоря, оператор break используется для выхода из оператора switch.
Методы класса
В начале статьи я упомянул, что наши домашние животные могут перемещаться и есть. В отличие от параметров вроде веса и клички, это уже не свойства объекта, а его функции. В классе эти функции обозначают как методы.
Метод класса — это блок кода, состоящий из ряда инструкций, который можно вызывать по его имени. Он обязательно содержит возвращаемый тип, название, аргументы и тело метода.
Синтаксис метода в Java:
Строка возвращаемыйТип показывает, какого типа данные вернёт метод. Например, если в качестве возвращаемого типа мы поставим тип String, то метод должен будет вернуть строку, а если int — целое число.
Чтобы вернуть значение из метода, используется специальное слово return. Если мы хотим, чтобы метод ничего не возвращал, то вместо возвращаемого типа нужно использовать специальное слово void.
Аргументы — то, что нужно передать в метод при его вызове. Мы можем указать сколько угодно параметров через запятую либо не указывать ни одного.
Для примера напишем простейший метод с именем sum (пока что не в нашем классе Pet), который складывает два переданных числа и возвращает их результат:
Возвращаемый тип метода int, он указан перед именем sum. Далее идут два аргумента a и b, у обоих также указан тип int
Важно помнить, что возвращаемый тип и тип переменных не обязательно должны совпадать
Аргументы метода работают как обычные переменные — за пределами метода к ним никак нельзя получить доступ. Внутри метода мы складываем значения из переменных a и b, записываем полученное значение в переменную c. После этого мы возвращаем значение переменной c — только оно доступно вне метода.
Вот пример:
Мы передали в метод sum два значения 1 и 2, а на выходе получили результат их сложения 3. Также можно создать метод, который принимает значение типа String, а возвращает длину этой строки:
В этом случае у нас возвращаемый типа int, а параметр str — типа String.
Попробуем использовать этот метод:
Также мы можем создать метод, который ничего не возвращает, а просто печатает переданное слово в консоль:
Либо метод, который ничего не принимает на вход, а просто печатает «Привет!»:
В методах, которые ничего не возвращают, слово return можно опустить.
Обратите внимание, что return полностью прекращает выполнение метода:
Теперь попробуем вызвать этот метод, передав в него число 3:
В этом случае мы ничего не увидим в консоли, так как 3 меньше 5, а значит, отработает блок if и произойдёт выход из метода с помощью слова return.
Но если передадим 6, увидим нашу надпись «Привет!»:
Обновлённый оператор switch в Java 14
С версии 14 Java поддерживает новый синтаксис switch:
Теперь нам не нужно писать break, а двоеточие заменено на стрелочку и фигурные скобки. Блок default по-прежнему не обязателен.
Если код блока case состоит всего из одной строки, то фигурные скобки можно не использовать:
В операторе switch прошлой версии мы задавали одно действие для нескольких значений case, располагая пустые case над case c кодом:
В новой версии для этого хватает одного case, а связанные с ним значения разделяются запятой. Например:
Теперь switch — уже не просто оператор ветвления, он может вернуть значение. Это делается с помощью вспомогательного оператора yield.
Пример:
В новой версии switch, когда нам нужно лишь вернуть значение из соответствующего case (он должен быть без кода), — можно обойтись и без слова yield:
Советы и упрощения
1. Фигурные скобки после if или else разрешено не ставить, если тело блока состоит всего из одной строки.
Однако всё же советую ставить скобки, так вы научитесь быть последовательными и облегчите рефакторинг кода.
2
Вот так писать не следует (внимание на условие в if):. Код будет работать, но сравнение boolean с boolean в условии — это лишняя операция
Код будет работать, но сравнение boolean с boolean в условии — это лишняя операция.
Поскольку метод isMoreFive сам возвращает булево значение — напишите вот так:
Здесь снова ненужное сравнение:
Чтобы не было лишней операции — пишите вот так: