После изучения функций, условий и циклов стоит поговорить об области видимости переменных — то есть, где переменные “видны” и доступны для использования.
В примере программы ниже можно увидеть, что внутри if была определена строковая переменная d и после блока if совершается попытка вывести ее содержимое на консоль. Однако, она недоступна вне блока if.
Этот код не скомпилируется, так как все переменные, которые создаются внутри блока if НЕ ВИДНЫ внешнему блоку, то есть функции main.
Это касается не только if, а и for, switch, else и тому подобное.
class Test {
static int averageOf3Nums(int a, int b, int c) {
int sum = a + b + c;
int resultAverage = sum / 3;
return resultAverage;
}
public static void main(String[] args) {
String b = “Some text info!”;
String c = “Some text info!”;
if (b.equals(c)) {
String d = b + c;
}
System.out.println(d);
}
}
Вывод:
Чтобы переменная была доступна вне блока, её нужно объявить заранее, до входа в if:
class Test
{
static int averageOf3Nums(int a, int b, int c) {
int sum = a + b + c;
int resultAverage = sum / 3;
return resultAverage;
}
public static void main(String[] args)
{
String b = “Some text info!”;
String c = “Some text info!”;
// Создаем переменную заранее
String d = “”;
if (b.equals(c)) {
// Записываем результирующую строку
// в уже созданную ранее переменную
d = b + c;
}
// Выводим ее на консоль
System.out.println(d);
}
}
В этом уроке мы познакомимся с понятием функций, которые в Java все же корректнее называть методами. Несмотря на это, термин “функция” широко используется и в Java, поэтому для удобства будем придерживаться именно его.
До этого мы уже употребляли некоторые функции — например, println() для вывода строки в консоль или replace() для замены символов в строке и т.д.
Говоря просто, функция — это единица кода, которая выполняет определенное действие над переданными ей данными.
Важно понимать, что все процессы, которые выполняют это действие (то есть код, который реализует процессы выполняющие это действие) скрыты от наших глаз — они происходят “за кулисами”.
То есть в программе мы просто написали название функции, передав ей какие-либо аргументы (аргументы это то, что передается функции в круглых скобочках () ) и она выполняет то или иное действие.
И эту функцию можно таким образом вызывать много раз по ходу программы.
К примеру, представьте, что мы вызвали функцию equals много раз по ходу программы.
А теперь представьте если бы для сравнения двух строк на каждом месте где вызывается эта функция мы бы писали не вызов equals, а то, что внутри equals, то есть код, который реализует процессы сравнения двух строк и собственно выполняет сравнение двух строк, то есть код, которыйпод капотом у equals, а этот код это не одна строчка кода, и очевидно, что на каждом месте где у нас раньше был вызов equals, эти строчки кода из equals будут повторяться. Что очевидно не есть хорошо. Вызов функции это одна строчка кода, а то что у нее под капотом это много строчек кода. Лучше повторять одну строчку кода, чем повторять много строчек кода.
И здесь очевиден смысл функций!!
Вынося код в функцию, а не многократно повторяя его по ходу программы мы уменьшаем количество повторяющегося кода, что ясное дело делает его намного читабельнее.
Более наглядно на примере программы:
class Test
{
public static void main(String []args)
{
String b = “Some text info!”;
String c = “Some text info!”;
String d = “Some text inrwgf!”;
if(b.equals(c)) { //Если бы здесь,
System.out.println(“b and c are equal strings!”);
}
System.out.println(b.equals(c));// здесь,
System.out.println(c.equals(d));// и здесь,
//для сравнения строк вместо вызова equals был бы
//код, который под капотом у функции equals
//то очевидно было бы много повторяющегося кода кода.
}
}
Создание функции
Создадим функцию, которая вычисляет среднее арифметическое трёх чисел: складывает их, делит сумму на три и выводит результат на консоль. Ниже приведен пример создания этой функции.
Пока не обращайте внимание на слова static и void, их разберем позже.
averageOf3Nums – это имя нашей функции (по аналогии с функцией equals, где equals – это имя функции).
По этому имени будет вызываться наша функция для нахождения ср. арифметического.
В скобочках через запятую определяються аргументы, которые будут передаваться в функцию – какого они типа и сколько их. Как видим, это будут три числовых значения.
Внутри же этой функции находиться код который реализует процессы нахождения среднего арифметического трех чисел: он выполняет действия над переданными аргументами и выводит результат.
Пример создания функции:
class Test
{
static void averageOf3Nums(int a, int b, int c) {
int sum = a + b + c; // сложить 3 числа
int resultAverage = sum / 3; // поделить на их количество
System.out.println(resultAverage); // вывести на консоль ср. ар.
}
public static void main(String[] args)
{
// В main используем функцию, определенную выше.
// Ниже вместо a будет подставлено 6,
// вместо b будет подставлено 9,
// а вместо c будет подставлено 34.
// И все действия, которые выполняются с a, b, c
// в функции выше, будут выполняться с 6, 9, 34.
// В переменной resultAverage окажется
// среднее арифметическое этих чисел,
// и оно будет выведено на консоль.
averageOf3Nums(6, 9, 34);
// Вызовем еще пару раз с другими числами.
averageOf3Nums(9, 44, 11);
averageOf3Nums(3, 12, 4);
}
}
Вывод:
Код выше можно было бы переписать без функции.
class Test
{
public static void main(String []args)
{
int sum, resultAverage;
sum = 6+9+34; // сложить 3 числа
resultAverage = sum/3; // поделить на их количество
System.out.println(resultAverage); // вывести на консоль
sum = 9+44+11;
resultAverage = sum/3;
System.out.println(resultAverage);
sum = 3+12+4;
resultAverage = sum/3;
System.out.println(resultAverage);
}
}
Вывод:
То, о чем мы говорили: много повторяющегося кода. Это неудобно и неэффективно, так как вместо одной строчки приходиться каждый раз писать три.
Возвращаемое значение функции
Если вспомнить функцию equals, мы помним, что она возвращала true или false.
То есть результатом выполнения функции equals является booleanзначение.
Наша же функция averageOf3Nums возвращала void(это ключевое слово можно увидеть перед именем).
Это ключевое слово значит, что функция не должна возвращать ничего. И наша функция ничего и не возвращала, она просто выполняла некоторые вычисления и потом вызывала функцию println для вывода результата вычислений на консоль.
Таким образом, ключевое слово перед именем функции – это тип возвращаемого функцией значения.
Пример функции, которая возвращает значение:
class Test {
// Теперь наша функция уже не void и должна
// возвращать число типа int (int перед именем)
static int averageOf3Nums(int a, int b, int c) {
int sum = a + b + c;
int resultAverage = sum / 3;
// Действительно, resultAverage — это число типа int.
// Поэтому ключевым словом return можем вернуть
// это число как результат функции
return resultAverage;
}
public static void main(String[] args) {
// Нам уже незачем просто вызывать функцию, как в строке кода ниже —
// это бессмысленно, так как результат функции никуда не сохраняется.
// Число, которое возвращает функция, должно быть как-то использовано.
averageOf3Nums(6, 9, 34);
// Например, можно записать возвращаемое значение в переменную:
int average = averageOf3Nums(6, 9, 34);
// А затем передать её в функцию для вывода на консоль:
System.out.println(average);
// В результате на консоли увидим среднее арифметическое
}
}
В прошлых уроках мы уже сталкивались со строками, когда передавали текст в кавычках "" в функцию вывода на консоль — например: System.out.println("строка").
Ранее мы называли это просто текстом, но правильнее использовать термин строка.
Строка — это набор любых одиночных символов, например 'g', '2', '-', обьединенных вместе.
Ранее мы изучали тип данных char, который хранит один символ. Так вот, строка состоит из последовательности символов типа char.
Например, можно объединить символы, которые мы привели выше, и получится строка "g2-". Как видно, строка всегда записывается в двойных кавычках, в отличие от одиночных кавычек у символов char.
Приведем пример строк в программе:
class Test
{
public static void main(String []args)
{
//Строки можно хранить в переменной типа String
String b = “Some text info!”;
//Выведем строку только теперь не напрямую как раньше,
//а из переменной b.
System.out.println(b);
}
};
Вывод:
Склеивание (конкатенация) строк
Строковые переменные можно объединять в одну строку с помощью “+”.
Пример конкатенации:
class Test
{
public static void main(String []args)
{
String b = “Some”;
String c = ” text info!”;
String d = b+c;
//выводим объединенный текст переменных a и b
System.out.println(d);
}
}
Вывод:
Обход символов строки с помощью цикла
По символам строки можно пройтись циклом, аналогично тому, как мы это делали с массивами.
То есть можно получать каждый символ строки по индексу и по порядку выводить их на консоль.
Количество символов в строке можно узнать с помощью функции length().
В отличие от массивов, для получения символа по индексу в строке используются не квадратные скобки, а специальная функция charAt(), в которую передаётся индекс нужного символа.
Пример обхода строки:
class Test
{
public static void main(String []args)
{
String b = “Some text info!”;
for(int i=0; i < b.length(); i++){
System.out.println(b.charAt(i));
}
}
}
Вывод:
Другие полезные функции у строк
Ранее мы уже использовали функцию length для получения длины строки и CharAt для получения символа строки по индексу. Но также у строк в Java есть много других полезных функций.
Например, функция equals() используется для сравнения строк. Она возвращает true, если строки полностью совпадают.
Или, например, функция replace() которая позволяет заменить символы или подстроки в строке.
Пример использования этих функций:
class Test
{
public static void main(String []args)
{
String b = “Some text info!”;
//Заменим все буквы t в строке выше на букву G.
//Для этого используем функцию replace.
//Первый аргумент, который передается в функцию
//это символ, который нужно заменить в строке,
//второй аргумент это символ, который встанет на место
//символа, который мы заменяем.
System.out.println(b.replace(‘t’,’G’));
//То есть на консоль выведется Some GexG info!
//Важное уточнение, что сама переменная b все еще
//содержит строку “Some text info!” не измененной.
//Функция replace работает так, что она КОПИРУЕТ
//содержимое String переменной и делает изменения
//над КОПИЕЙ, а не самим содержимым строки b.
String c = “Some text info!”;
//Проверим с помощью equals одинаковы ли строки b и c.
if(b.equals(c)){
//если строки одинаковы выводим сообщение об этом
System.out.println(“b and c are equal strings!”);
}
}
};
В этом уроке мы познакомимся смассивами в Java: разберём их концепцию, научимся с ними взаимодействовать и узнаем, какие типы массивов бывают.
В прошлых уроках у нас была переменная int a=31 хранящая одно число 31.
А что если мы хотим иметь переменную в которой будет храниться 100 разных числовых значений?
Такая переменная называется массивом.
Объявляется массив так:
int[] a;
[] значат, что это массив и в нем будет храниться много значений (значений типа int в данном случае).
Пока массив а был просто объявлен. Чтобы в него поместить значения нужно выделить место в памяти где будут храниться значения массива и указать конкретное количество значений, которое может храниться в массиве.
Ключевым словом new мы выделяем память под массив, который может вмещать максимум 5 элементов.
a = new int[5];
После этого можно записывать в эту память числа.
Объявление и выделение памяти можно записать в одну строку как:
int[] a = new int[5];
Также можно при создании массива сразу записать в них значения.
int[] b = {56, 3, 7, 63, 13};
Заранее с помощью new память под эти значения выделять не нужно, так как мы сразу записываем в память значения.
Взаимодействие с массивом
Итак рассмотрим как мы можем взаимодействовать с массивом.
Ниже в примере программы создается массив b, который содержит 5 числовых значений.
Каждое из пяти значений имеет свой порядковый номер в массиве:
56 – имеет номер 0, 3 – имеет номер 1, 7 – имеет номер 2, 63 – имеет номер 3, 13 – имеет номер 4. Очевидно, что номера элементам массива выдаются по порядку, то есть первому элементу в массиве номер ноль, второму номер 1, третьему элементу номер 2 и т.д.
Также как видим порядковый номер в массивах начинается с нуля, а не единицы.
Правильно этот порядковый номер в массиве называть индексом.
Поясним на примере:
class Test
{
public static void main(String []args)
{
int[] b = {56, 3, 7, 63, 13};
// По индексу мы можем взаимодействовать
// с элементами массива.
// Например, ниже мы записываем
// в элемент массива с индексом 1 число 33.
// Индекс указывается в квадратных скобках.
// Теперь вместо 3 теперь будет 33.
b[1] = 33;
// Можно обратиться к элементу по индексу
// чтобы его использовать каким-то образом.
// Например, вывести на консоль как ниже.
System.out.println(b[1]);
}
}
Вывод:
Обход массива циклом
Выведем все элементы массива b по порядку с помощью for.
Любой массив имеет внутри себя переменную length в которой храниться количество элементов массива. Это можно использовать для обхода элементов циклом.
Поясним на примере:
class Test
{
public static void main(String []args)
{
int[] b = {56, 3, 7, 63, 13};
//В данном случае b.length равно 5,
//так как в массиве пять элементов.
//Условие цикла как видим, такое, что пока i
//меньше длины массива (то есть пяти)
//цикл for продолжает свое выполнение.
for(int i=0; i < b.length; i++)
{
//Каждую итерацию цикла i увеличивается на 1,
//и эту i мы помещаем в квадратные скобки в качестве индекса
//для извлечения каждого элемента массива по индексу
//на каждой итерации.
//То есть на первой итерации на консоль выводится
//значение элемента b[0], на второй итерации значение
//элемента b[1] и т.д. до b[4]
System.out.println(b[i]);
}
}
};
Вывод:
Как видим, можно легко пройтись по элементам массива и совершать с каждым какие-то действия на каждой итерации. Например, выводить на консоль каждый элемент, как в приведенном примере.
Обход массива циклом for-each
Для обхода элементов массива можно использовать особенный вид for цикла.
Называется он for-each.
Используя цикл foreach нам ненужно знать размер массива.
В примере ниже цикл foreach начиная с первого элемента массива b поочереди берет элементы и помещает их в singleArrayElement
class Test
{
public static void main(String []args)
{
int[] b = {56, 3, 7, 63, 13};
for(int singleArrayElement : b){
System.out.println(singleArrayElement);
}
}
}
Вывод:
То есть на первой итерации этого цикла берется первый элемент массива b и помещается в переменную singleArrayElement, которая того же типа, что и массив b и в теле цикла можно работать с первым элементом массива через эту переменную, на второй итерации цикла второй элемент помещается в singleArrayElement вместо первого и происходит работа уже со вторым элементом массива, на третьей помещается третий и т.д. до конца массива.
Важно знать: singleArrayElement — это копия значения элемента массива, а не сам элемент. Это означает, что изменяя singleArrayElement в теле цикла, вы не изменяете сам массив.
Однако, если массив содержит объекты (которые мы ещё не проходили), а не простые типы данных, то for-each работает с самим объектом, а не с его копией
Двумерные массивы
До этого мы рассматирвали одномерный массив, но массивы также бывают многомерными.
Представьте одномерный массив, в котором каждый элемент — это полноценный одномерный массив чисел, такой же, как мы рассматривали выше.
То есть это массив массивов чисел, и он называется двумерным массивом.
Ниже приведён пример двумерного массива. Он объявляется с помощью [][]. Как видно, через запятую перечислены массивы чисел — каждый из них является отдельным элементом основного массива.
В первой скобочке мы пишем индекс нужного нам подмассива.
Во второй скобочке пишем индекс нужного нам элемента (в нашем случае числа) этого подмассива.
Пример: строка кода ниже достает из массива b число 2. Мы обращаемся ко второму подмасиву, к третьему элементу этого подмассива.
System.out.println(b[1][2]);
Помним что элементы в массивах нумеруются начиная с нуля. Поэтому 1 и 2, а не 2 и 3.
Полный пример:
class Test
{
public static void main(String []args)
{
// Ниже пример двумерного массива.
// Как видим, через запятую перечислены массивы чисел.
int[][] b = {
{56, 3, 63, 13},
{3, 67, 2},
{5, 5, 3, 7, 9}
};
// Выведем третий элемент во втором подмассиве.
System.out.println(b[1][2]);
}
}
Вывод:
Обход двумерного массива циклом
По двумерному массиву можно пройтись с помощью любого вида цикла, который мы рассматривали ранее. Так как двумерный массив состоит из массивов внутри массива, для его обхода используются вложенные циклы.
Для простоты воспользуемся for-each. Ниже показано, как с помощью вложенных циклов пройтись по всем числам в двумерном массиве и вывести их на консоль.
Пример программы:
class Test
{
public static void main(String []args)
{
int[][] b = {
{56, 3, 63, 13},
{3, 67, 2},
{5, 5, 3, 7, 9}
};
System.out.println(b[1][2]);
// Внешний foreach по очереди записывает в single2DSubArray
// один из подмассивов двумерного массива b. Таким образом
// single2DSubArray перезаписываеться новым подмассивом каждую итерацию.
for(int [] single2DSubArray : b){
// Внутренний foreach ниже перебирает числа из текущего подмассива,
// который внешним foreach был записан в переменную single2DSubArray.
for(int singleArrayNumber : single2DSubArray){
// Через запятую выводим числа подмассива в single2DSubArray
System.out.print(singleArrayNumber + “, “);
}
// После обработки каждого подмассива внутренним for-each
// происходит переход на новую строку с помощью \n.
// Это позволяет визуально отделить выводимые подмассивы
// друг от друга при выводе в консоль.
System.out.println(“\n”);
}
}
}
В данном уроке рассмотрим ключевые слова break и continue.
Если нужно раньше времени остановить цикл по какому-то условию, то используется ключевое слово break.
Поясним на примере:
class Test
{
public static void main(String []args)
{
int a=31;
for(int i=0;i<10;i++){
// Каждую итерацию цикла от a отнимается единица
// и если переменная a на какой-либо итерации станет равна 25,
if (a==25) {
// то цикл завершает свою работу с помощью ключевого слова break.
break;
}
System.out.println(a);
a--;
}
}
};
Вывод:
Как видим произошло всего 6 итераций вместо 10. Очевидно что цикл for остановился досрочно, то есть іне дошло до 10. Цикл был остановлен с помощью break когда переменная астала равна 25.
Ключевое слово continue
Ключевое слово continue завершает одну текущую итерацию цикла досрочно.
Пример программы:
class Test
{
public static void main(String []args)
{
int a=31;
for(int i=0; i<10; i++) {
System.out.println(a);
// Каждую итерацию цикла от a отнимается
// единица, и если переменная a на
// какой-либо итерации станет равна 25,
if (a==25) {
// то досрочно останавливаем эту итерацию цикла
// и сразу происходит переход к следующей, то есть
// код после if (в данном случае это a--;)
// выполнен не будет.
continue;
}
a--;
}
}
}
Вывод:
Как видно из вывода, на седьмой итерации переменная a становится равной 25. Начиная с этого момента и до конца цикла (то есть пока i не станет равным 10), условие a == 25 продолжает выполняться, из-за чего срабатывает continue, и a--больше не выполняется. Поэтому на всех оставшихся итерациях значение a остаётся равным 25, что также видно в выводе.
Цикл может пригодиться в программе если нужно повторять какое-о действие или набор действий определенное количество раз.
Есть три вида циклов: for, while и do..while.
Для начала рассмотрим цикл while на простом примере:
class Test
{
public static void main(String []args)
{
int A=31, B=15;
//while означает “ПОКА”.
//ПОКА A не равно B, выполняется код внутри фигурных скобок.
while(A!=B){
//Одно повторение цикла, называется итерацией цикла.
//Можно сказать, что одна итерация цикла
//это одно выполнение двух строчек кода ниже.
System.out.println(A); //вывод значения А каждую итерацию.
A--; //каждую итерацию цикла от А отнимается 1
}
//Пока выражение в скобочках рядом с while не вернет ложь
//код в {} будет продолжать выполняться.
}
};
Вывод:
Что происходит при запуске:
Каждую итерацию значение A уменьшается на 1. Когда A становится равным B (то есть 15), условие A != B становится ложным, и цикл завершает выполнение.
Цикл for
Цикл for используеться чаще всего поскольку с помощью него условия выполнения цикла можно задать в очень копактной и удобной форме.
В программе ниже видно, что в круглых скобках после ключевого слова for находятся три выражения, разделённые точками с запятой:
for(инициализация; условие; обновление)
Поясним каждое из этих выражений.
Первоевыражение (инициализация)— выполняется единожды перед первой итерацией цикла for. В программе ниже первое, что происходит когда цикл for запускается, это создание целочисленной переменной i.
Второе выражение (условие)— это условие завершения цикла, при невыполнении которого цикл завершиться. Это аналог условию завершения цикла while который мы проходили выше.
Третьевыражение (обновление) — выполняется в конце каждой итерации цикла.
Пример программы:
class Test
{
public static void main(String []args)
{
int a=31;
for(int i=0;i<10;i++){
a--;
System.out.print(a+" ");
}
}
}
Вывод:
Что происходит при запуске:
Переменная iкаждую итерацию цикла увеличиваетсяна 1.
Цикл продолжается до тех пор, пока i не станет равной 10, то есть выполняется, пока i меньше 10.
Таким образом, всего выполняется 10 итераций.
На последней итерации переменная a будет равна 21.
Стоит упомянуть, что созданная нами переменная і при выходе из последнего цикла удаляется, она живет только в цикле.
Это самый часто используемый цикл, так как на место этих трех выражений можно ставить что угодно, что очень гибко и удобно.
Цикл do…while
Цикл do...while почти не отличается от обычного while, за исключением одного важного момента: условие проверяется в конце, а не в начале. Это означает, что тело цикла выполнится хотя бы один раз, независимо от условия.
В этом примере программы как раз можно увидеть что условие проверяеться в конце:
class Test
{
public static void main(String []args)
{
int a=31, b=15;
do {
System.out.print(a+” “);
a--;
} while(a!=b);
}
}
Вывод:
Таким образом в отличии от просто while в цикле do…while сначала выполняется код в {}, а потом проверка условия.
Иногда этот цикл бывает полезен. Но он самый не популярный и его вы будете встречать очень редко.
В прошлых уроках мы изучили операторы сравнения и логические операторы. В этом уроке рассмотрим как выражения с операторами можно использовать.
Чаще всего их используют в условных операторах. Например в if...else.
С помощью if...else можно проверить, даёт ли выражение значение true, и если да — выполнить определённые действия.
Поясним на примере.
class Test
{
public static void main(String []args)
{
int a=31, b=15;
//if означает “ЕСЛИ”.
//Если проговорить код ниже то будет:
//”ЕСЛИ а больше чем b то выполняется код в {} после if”.
if(a>b)
{
System.out.println(“a>b returned true”);
}
//else означает “ИНАЧЕ”.
//Если проговорить код ниже то будет:
//”ИНАЧЕ выполняется код в {} после else”.
//Имеется ввиду ИНАЧЕ от того что было
//в круглых скобочках у if.
//То есть то что в фигурных скобочках после else
//выполняется если выражение a>b вернуло false,
//если же a>b вернуло true и был выполнен код
//в фигурных скобочках у if то код в фигурных
//скобочках у else, очевидно, выполнен не будет.
else
{
System.out.println(“a>b returned false”);
}
//Выполниться то что в фигурных скобочках
//у if так как a>b возвращает true.
//То есть, как видим, можно писать блоки кода,
//которые выполняются только по какому-то условию.
}
};
Вывод:
В примере if...else оператора ниже, выполниться то, что в фигурных скобочках после else, так как выражение a<b возвращает ложь.
class Test
{
public static void main(String []args)
{
int a = 31, b = 15;
if (a < b) {
System.out.println("a < b returned true");
}
else {
System.out.println("a < b returned false");
}
}
};
Вывод:
if можно писать отдельно от else и если то, что в круглых скобочках ложно, то ничего не произойдет, так как у нас уже нет блока else.
class Test
{
public static void main(String []args)
{
int a = 31, b = 15;
if (a < b) {
System.out.println("a < b returned true");
}
}
};
Вывод:
Также есть else if (...) {...}. Его можно писать много раз для дополнительных проверок.
Пример программы:
class Test
{
public static void main(String []args)
{
int a=31, b=15;
// Если код в {} после if(a < b) не выполнялся,
// то есть a < b возвращает false,
if(a < b){
System.out.println("a < b returned true");
}
// то выполняется проверка условия в else if ниже
// и если a==b возвращает true, то выполняется код
// в {} после else if(a==b) и все проверки далее
// совершаться не будут, то есть произойдет переход к коду
// после проверок, то есть к строчке:
// System.out.println("The end of the program");
// Если же a==b возвращает false
else if(a==b){
System.out.println("a < b returned false, but a==b "
+ "returned true");
}
// то выполняется проверка условия в else if ниже
// и если a>b возвращает true, то выполняется код
// в {} после else if(a > b) и все проверки далее
// совершаться не будут, то есть произойдет переход к коду
// после проверок, то есть к строчке:
// System.out.println(“The end of the program”);
// Если же a > b возвращает false
else if(a > b){
System.out.println(“a < b returned false, a==b "
+ "returned false, but a > b returned true”);
}
// то выполняется код в {} после else.
else{
System.out.println(“a < b returned false, a==b returned false"
+ " so lets return something in else block");
}
System.out.println("The end of the program");
// Программа выполнит то,
// что в фигурных скобках у else if(a>b),
// так как a > b возвращает true.
}
};
Вывод:
Как уже было замечено, если бы, например, a==b возвращал true в программе выше, то все другие проверки else if после else if(a==b) не совершались бы и блок else тоже не выполнился бы.
В этом смысл else if. Если бы вместо всех else if были использованы просто if, и при этом условие a == b оказалось бы истинным, то код в скобочках {} этого условия бы выполнился, но программа дальше бы продолжила проверки условий в if-ах ниже этого условия.
То есть смысл в том, что из всех else if будет выполнен только один и если какой-то else if выполнился, то все остальные проверки else if за ним совершаться не будут.
Условный оператор switch case
Также часто вместо if…else используют switch case.
Давайте для начала приведем if else версию, а потом ее switch case аналог, который делает то же самое.
Пример программы:
class Test
{
public static void main(String []args)
{
int a=31, b=15;
//если a+b равняется 35
if(a+b==35)
{
//то выполняется то что здесь
System.out.println(“a+b equals to 35”);
}
//если a+b равняется 46
else if(a+b==46)
{
//то выполняется то что здесь
System.out.println(“a+b equals to 46”);
}
//если a+b равняется 42
else if(a+b==42)
{
//то выполняется то что здесь
System.out.println(“a+b equals to 42”);
}
//если все условия выше оказались false
else {
//то выполняется то что здесь
System.out.println(“lets return somethong ” + “in else block”);
}
}
};
Вывод:
Ниже switch case версия, которая выполняет то же самое, что if версия выше.
Поочередно проверяются числа рядом с case-ами на предмет равенства результату выражения в скобочках рядом со switch и если в программе ниже, например, число 42 окажется равным результату выражения a+b, то выполниться код между case 42: и break;.
Пример программы:
class Test
{
public static void main(String []args)
{
int a=31, b=15;
switch (a+b) {
case 35: //если a+b равняется 35
System.out.println(“a+b equals to 35”);
break;
case 46:
System.out.println(“a+b equals to 46”);
break;
case 42:
System.out.println(“a+b equals to 42”);
break;
default: //default аналог else
System.out.println(“lets return somethong in default block”);
}
}
};
Вывод:
Конструкция switch-case может быть менее громоздкой по сравнению с if-else в некоторых ситуациях. Она особенно удобна, когда в программе предполагается множество ветвлений вида else if (...). В таких случаях switch-case может быть предпочтительнее и с точки зрения производительности: компилятор может сгенерировать так называемую jump table, что ускоряет выбор нужного варианта.
Тем не менее, на практике чаще используется конструкция if...else, поскольку она более гибкая и подходит для сложных логических условий.
Логических операторов всего три – “И”, “ИЛИ” и “НЕ”.
В Java воспользоваться оператором “И” можно используя символы "&&", оператором “ИЛИ” используя "||" и оператором “НЕ” используя "!".
Логические операторы“И” и “ИЛИ” позволяют соединять несколько условий в одном выражении. То есть можно вставить логический оператор между двумя выражениями с опреатором сравнения, например между 6<3 и 2<4, и тогда получиться новое выражение уже с логическим опретором которое тоже будет возвращать true или false
Например, 6<3 && 2<4.
Давайте проговорим это выражение как делали в прошлых уроках – “6 меньше чем 3 И 2 меньше чем 4”. Верно ли такое утверждение? Нет. Значит результатом выражения будет false. Так как утверждение, что 6 меньше чем 3 ложно. Чтобы выражение с логическим оператором “&&” вернуло true нужно, чтобы И то, что стоит справа от логического оператора вернуло true, И то, что стоит слева от него вернуло true.
6<3 || 2<4 уже вернет true. Так как если проговорить, уже будет – “6 меньше чем 3 ИЛИ 2 меньше чем 4”. То есть, чтобы выражение с логическим оператором “||” вернуло true, нужно чтобы ИЛИ то, что стоит справа от логического оператора вернуло true, ИЛИ то, что стоит слева от него вернуло true.
Логический оператор отрицания “НЕ” в отличии от предидущих двух логических операторов не используеться между двумя выражениями, а применяеться к одному единственному выражению.
Например, !(6<3) вернет true. Это выражение нужно понимать, как обратный результат к выражению 6<3. То есть это НЕ (6 меньше чем 3). Оператор “!” просто оборачивает результат выражения на противоположный. Выражение 6<3 возвращает false, а обратное к false – это true, поэтому !(6<3) возвращает true.
Программа с логическими операторами:
class Test
{
public static void main(String []args)
{
// записываем в boolean переменную
// результат выражения 6<3 && 2<4
boolean a = 6<3 && 2<4;
// выведет false
System.out.println(a);
// выведет true
System.out.println(6<3 || 2<4);
// выведет true
System.out.println(!(6<3));
}
}
Операторы сравнения нужны, как можно догадаться, чтобы сравнивать. Сравнивать одно значение с другим.
Например: 6 < 3.
Знак > — это оператор “меньше чем”. То есть если проговорить это выражение, то будет “шесть меньше чем три”.
Вы скажете: «Это же неправда, шесть больше трёх!» — и вы будете правы. В Java результат такого сравнения будет false (то есть «ложь»).
И этот результат можно сохранить в boolean переменную. Помним, что boolean хранит либо true (правда), либо false (ложь).
Также есть и другие операторы сравнения:
больше чем – “>”
равняется – “==”
не равняется – “!=”
больше или равно – “>=”
меньше или равно – “<=”
Попробуйте поочерёдно подставить эти операторы между 6 и 3, проговорить получившееся выражение в уме и подумать, какой результат вернёт программа — true или false.
Пример программы:
class Test
{
public static void main(String []args)
{
//записываем в boolean переменную результат выражения 6<3
boolean a = 6 < 3;
//выведет false
System.out.println(a);
a = 6 > 3;
//выведет true
System.out.println(a);
a = 6 == 3;
//выведет false так как 6 не равен 3
System.out.println(a);
a = 6 != 3;
//выведет true так как 6 не равен 3
System.out.println(a);
a = 6 >= 3;
//выведет true так как 6 больше или равно 3
System.out.println(a);
a = 6 <= 3;
//выведет false так как 6 больше 3
System.out.println(a);
}
}
Есть пять типов операторов: операторы присвоения, арифметические операторы, операторы сравнения, логические операторы и условные операторы.
С одним оператором присвоения мы уже познакомились – это знак равенства.
int А = 5;
Как можно догадаться, операторы присвоения нужны для присвоения чего-то чему-то. Присвоение пятерки переменной А в данном случае.
Остальные операторы присвоения рассмотрим после арифметических.
Арифметические операторы нужны для выполнения простейших арифметических операций:
‘+’ – сложение
‘-‘ – отнимание
‘*’ – умножение
‘/’ – деление
‘%’ – остаток от деления
Пример использования арифметических операторов:
import java.util.Scanner;
class Test
{
public static void main(String []args)
{
//создадим две целочисленные переменные
//и сразу добавим в них значения
int A = 31, B = 15;
//запишем их сумму в новую переменную C
int C = A + B;
//и выведем результат сложения в консоль
System.out.println(V);
//перезапишем в C теперь разницу A и B и выведем
C = A – B;
System.out.println(C);
//то же самое с остальными операциями
C = A * B;
System.out.println(C);
C = A / B;
System.out.println(C);
//можно вывести напрямую, например, остаток от деления
System.out.println(A % B);
}
}
Можно увидеть результаты вычислений:
Склеивание текста
Также с помощью оператора сложения + можно склеивать текст.
import java.util.Scanner;
class Test
{
public static void main(String []args)
{
//склеим “Some text” и ” some another text”
//чтобы вывело “Some text some another text”
System.out.println(“Some text” + ” some another text”);
//также можно текст склеивать с числовыми значениями
int A = 31, B = 15;
int C = A + B;
System.out.println(“Variable A + B = ” + C + “. That`s cool”);
//в результате получится текст:
//”Variable A + B = 46. That`s cool”
}
}
В выводе можно увидеть, что оператор сложения успешно склеил “Some text “ и “some another text” и склеенное в итоге было выведено на консоль. Также оператор сложения успешно склеил число 46 из переменной C с кусками текста в один единый текст.
Добавление числа к переменной
Если переменная A содержит какое-либо значение и нам нужно сложить его с другим значением и поместить получившуюся сумму в эту же переменную A, то можно это сделать в одну строчку такой конструкцией:
import java.util.Scanner;
class Test
{
public static void main(String []args)
{
int A = 31;
// складываем содержимое A
// с другим числом и помещаем в A.
A = A + 10; // будет 41
System.out.println(A);
}
}
Вывод:
Для того чтобы выполнить данную операцию в еще более сокращенной форме используется оператор присвоения +=.
import java.util.Scanner;
class Test
{
public static void main(String []args)
{
int A=31;
// складываем содержимое A
// с другим числом и помещаем в A.
A+=10; // будет 41
System.out.println(A);
}
}
Вывод будет такой же.
Такие операторы присвоения есть и для всех остальных базовых арифметических операций: -=, *=, /=, %=.
Инкремент и декремент
Также важно упомянуть оператор инкремента ++ и декремента --.
Запись a++ значит, что переменная а будет увеличена на 1. Это то же самое, что написать a=a+1.
То же самое с декрементом.
import java.util.Scanner;
class Test
{
public static void main(String []args)
{
int a = 31;
// Инкремент
a++; // будет 32
System.out.println(a);
// Декремент
a--; // будет 31
System.out.println(a);
}
}
Вывод:
Пре-инкремент и пре-декремент
Также еще есть пре-инкремент ++A и пре-декремент --A.
До этого мы рассматривали пост-инкремент A++ и пост-декрементA--.
Продемонстрируем разницу между ними.
class Test
{
public static void main(String []args)
{
int A=31;
// Выполнение строчки кода ниже происходит
// в такой последовательности, что сначала
// происходит вывод, то есть срабатывание
// функции println, а потом к переменной
// а прибавляется единица. То есть в результате
// выполнения строчки кода ниже на консоль будет
// выведено 31. Это пост-инкремент.
System.out.println(A++);
// После выполнения верхней строчки кода
// переменная A уже теперь содержит 32.
// Можно это проверить. Для этого выведем
// содержимое A еще раз.
System.out.println(A);
// Сейчас переменная A содержит значение 32.
// Теперь используем пре-инкремент.
// Последовательность выполнения строчки
// кода ниже обратна предыдущему случаю, то есть
// сначала происходит прибавление единицы к переменной A,
// а потом вывод переменной A на консоль.
// То есть строчка кода ниже выведет на консоль 33.
System.out.println(++A);
// Пре-декремент и пост-декремент
// работают таким же образом.
}
}
Вывод:
Еще раз про разницу.
При пост-инкременте (A++) сначала выполняется действие с переменной (в нашем случае — вывод на консоль), и только потом к ней прибавляется 1.
При пре-инкременте (++A) наоборот — сначала к переменной прибавляется 1, а уже затем выполняется действие.