• Авторизация


Программирование на Java: от ламера - чайнику. Пост №2.2. Операторы и конструкции. Матерные. 04-12-2013 00:00 к комментариям - к полной версии - понравилось!


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

Сегодня у нас массивы, циклы и на закуску - ещё кое-что о переменных:)


Ящики с пивомМассивы.

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

В Java можно создавать массивы любого типа, от примитивных до тех, что мы сами описали и определили. Мы рассмотрим массивы типа int. Объявляются массивы так:

int[] имя_массива;//вариант 0

int имя_массива[];//вариант 1

Оба объявления равнозначны и какое использовать - дело вкуса. Я лично предпочитаю 0-ой вариант:)

Итак, объявили массив. Круто, мы молодцы. Но его же ещё надо инициализировать. Делается это так:

имя_массива = new int[n];//вариант 0

имя_массива = new int[]{0, 1, 2, 3};//вариант 1

Я вижу панику на ваших лицах:) Уже который раз в кусках кода встречаются символы // с последующим текстом за ними, а я ещё не объяснил, что это такое:) Эти символы задают однострочный комментарий, то есть всё от этих символов и до конца текущей строки не воспринимается как программный код и не используется при построении приложения. Есть ещё последовательность /* ... */. Это не смайлик:) Это многострочный комментарий. Делает тоже самое, что и однострочный, но любой текст между этими символами не воспринимается комьютером как код программы. Такие вещи используют, когда нужно пояснить другим программистам да и себе, как работает какой-то кусок кода.

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

Вариант 1 делает тоже самое, но в фигурных скобках мы указываем элементы в том порядке, в котором они будут следовать в массиве и элементы массива инициализируются этими значениями, а не значениями по умолчанию. Вы можете сказать, что мы не указали размер, но в данном варианте это не страшно - компьютер умный, он сделает это за нас, посчитав количество указанных элементов:) Кстати, это единственный случай, когда за фигурной скобкой ставится ";", если фигурная скобка означает границу блока кода - там не нужна точка с запятой.

Объявление и инициализацию можно объединить и написать в одну строку. Но вы это уже видели на примере простых переменных, вы сможете это сделать:) Запомните ключевое слово new, оно вам очень понадобится. По сути это слово создает новый объект указанного класса.

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

имя_массива[1] = имя_массива[3];

Кстати, вопрос на засыпку: чему был равен и будет равен 1-ый элемент нашего массива после выполнения этой строчки кода?:) Не угадали:) Был равен 1, стал равен 3. Не кидайте в меня тапками - я поясню:) Дело в том, что в программировании нумерация чего бы то ни было начинается с нуля. То есть индекс первого элемента(это у нас 0) равен 0, второго(он у нас 1) - 1 и так далее. Помните: максимальный номер элемента в массиве всегда на 1 меньше его размера. Если пытаться обратиться к элементу с номером 4 в массиве размером в 4 элемента, мы получим исключительную ситуацию - мы же вылезем за пределы массива. По аналогии с однорядным ящиком пива - мы попытаемся взять бутылку которой нет и никогда не было в ящике:)

С элементами массива можно производить те же операции что и с обычными переменными. А ещё можно сделать массив по аналогии с настоящим ящиком пива - многорядным:) Это называется двумерный массив. Как? А вот так:

int[][] имя_массива;//объявление

имя_массива = new int[10][10];//инициализация начальными значениями по умолчанию

int i = имя_массива[1][2];//переменной i присваиваем значение элемента в 1-ой строке 2-ом столбце

Всё тоже самое, только индексов теперь два. И доступ ведется по двум индексам. Для понимания проще представить таблицу или обычный ящик пива:) А можно сказать что это обычный массив у которого каждый элемент - массив значений типа int:) Кому что ближе:)

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


Циклы.

Цикл - повторяющийся несколько раз фрагмент кода. Циклы бывают с постусловием, с предусловием и обычный цикл. Начём с обычного, он же цикл for. Его синтаксис выглядит так:
for(инициализация счётчика; условие; изменение счётчика){

//повторяющийся блок кода или тело цикла

}

Теперь как это работает. Инициализация счётчика - это инициализация переменной, которая будет считать число проходов цикла. Она инициализируется один раз перед началом работы цикла, доступна в теле цикла и уничтожается после его завершения. Условие - логическое условие, если оно истиннно или true - цикл совершит очередной проход, если оно ложно или false - будет выполнена следующая за телом цикла строка кода. Изменение счётчика - выражение которое изменяет счётчик, как правило это инкремент или декремент, но может быть и любое другое арифметическое выражение.

Могу привести аналогию, навеянную телефонным звонком. У меня рингтон - свист падающих авиабомб:) Вот есть у нас бомбардировщик с определенным запасом бомб. И вот дают ему задание - энное количество раз отутюжить бомбами заданный район. Что получается: пилот выходит на цель, сбрасывает бомбы и улетает на базу за новым комплектом. И после каждого такого вылета считает их количество. Когда это самое количество вылетов достигнет определенного значения - всё, задание выполнил, можно заниматься своими делами:)

Ну, ещё можно привести аналогию с выпиванием энного количества бутылок пива:) Берем много бутылок и по очереди их выпиваем, считая количество. Как только количество достигло какого-то значения(мы стали "застенчивыми":)) - прекращаем это дело:)

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

int [] arr = new int[100];

for(int i = 0; i < 100; i++){

arr[i] = 1000;

}

Вот так такой кусок кода и будет выглядеть. Разумеется в циклах можно выполнять не только такие простые действия, но и что-то посерьёзнее:)
Рассмотрим пошагово, что мы тут написали. Первая строка - объявление массива и инициализация значениями по умолчанию. Затем объявляется цикл, где переменная i это счётчик, который изначально равен 0, условие - i меньше 100, и инкремент в качестве изменения счётчика. На первом проходе i = 0, и элементу arr[0] присваивается значение 1000. Затем происходит увеличение счётчика на 1(инкремент). Затем проверяется условие и если оно истинно - проходит следующее повторение, которое называется итерацией. Когда i будет равно 100 - условие i < 100 не выполнится и тело цикла не выполнится. Вот так оно и работает.

Небольшое замечание: если бы мы определили переменную i до цикла, то она не уничтожилась бы после выполнения цикла, а сам цикл записался бы так:
int i;

for(i = 0; i < 100; i++){

arr[i] = 1000;

}

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

Цикл с предусловием ещё называют циклом "пока". Выглядит конструкция так:

while(условие){

//повторяющийся блок кода или тело цикла

}

Суть ещё проще, чем в предыдущем цикле - пока указанное условие истинно, блок кода будет выполняться. Но есть одно "но": если на момент входа в цикл, то бишь первой итерации, каким-то непонятным образом условие окажется ложным - цикл не выполнится, вообще, никак, ни за что:)

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

Если смотреть в аналогии про пиво, то это будет выглядеть так: допустим условие стоит пить пока не выпито всё. И вот перед каждой новой бутылкой пива мы будем проверять, а всё ли выпито, если нет - берем ещё бутылочку, если да - идём спать:)

Кстати, циклом while можно при некотором желании реализовать цикл for. А делается это вот так, если смотреть на предыдущий пример:

int[] arr = new int[100];

int i = 0;

while(i < 100){

arr[i] = 1000;

i++;

}

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

Цикл с постусловием - такая же байдистика, но проверка условия выполняется после отработки тела цикла, а не перед ней, как в двух предыдущих. Выглядит это так:
do{

//повторяющийся кусок кода или тело цикла

}while(условие);

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

Снова аналогия с бомбардировщиком:) Снова его посылают бомбить заданный район до состояния "выжженная земля", но теперь он сначала сбрасывает бомбы, а потом смотрит, осталось ли что живое. Если осталось - сделает ещё один вылет, если нет - вернётся на базу кофе пить:)

С пивом можно представить так:) Выпиваем бутылку и смотрим - а остались ли чипсы на закуску. Если остались - берем следующую бутылочку, если нет - идём спать:)

Перепишем ещё раз пример про массив, но уже на этом цикле:

int[] arr = new int[100];

int i = 0;

do{

arr[i] = 1000;

i++;

}while(i < 100);

Делает тоже самое, но в любом случае один раз выполнится.

Нельзя не упомянуть ещё один вид цикла for:

for(переменная : массив того же типа){

//тело цикла

}

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

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

Про пиво... Хм... Допустим, у вас есть определенное количество бутылок пива, массив пивных бутылок, так сказать:) И вот вы перебираете все и каждую выпиваете:)

Наш несчастный кусок кода с массивом можно переписать ещё раз вот так:

int[] arr = new int[100];

for(int i : arr){

i = 1000;

}

Действует так же, выглядит короче:)

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

Если по аналогиям - пилоту бомбардировщика пришёл приказ вернуться на базу и пить кофе, а в случае с пивом - пришла недовольная жена/девушка/соседи/полиция и пьянка кончилась:) Причём, как вы понимаете, такой приказ может прийти в любой момент: и во время вылета, и прямо перед сбросом бомбовой нагрузки, и когда пилот на базе

Например:

int i = 0;

for(i; i < 100; i++){

if(i == 50) break;

//Какие-то наши действия

}

System.out.prinln(i);

Его лучше использовать только с условием(об этом - в предыдущем посте), бо если в теле цикла просто стоит инструкция break;, дойдя до неё программа прервёт выполнение цикла и выйдет из него, а это может поломать весь алгоритм. И в итоге, программа будет работать не так, как надо.

В нашем примерчике цикл выполнится только наполовину, бо когда i станет равным 50, сработает наше условие, выполнится оператор break и произойдёт выход из цикла и выполнится строка с выводом.

 


Ещё кое-что о переменных.

Переменные же нужно называть, правильно? Так вот, называть их нужно правильно. Есть некоторые правила:

  1. Имена переменных должны начинаться сугубо с буковки, знака подчеркивания _ или знака доллара $. Если первый символ имени переменной вы напишете цифрой, придут боги программ и дадут по пальцам металлической линейкой, очень больно:) Шучу, просто программа работать откажется и даже не соберется.
  2. После первого символа может идти любые комбинации букв, циферок, знаков подчёркивания и доллара. Причём длина имени переменной не ограничена.
  3. Имена регистрозависимы, то бишь arr, ARR, Arr, ArR, aRr, ARr, arR, aRR - это 8 разных переменных:)
  4. Нельзя использовать в качестве имен переменных зарезервированные слова, такие как: abstract, boolean, break, byte, case, catch, char, class, const, continue, default, do, double, else, extends, final, finally, float, for, goto, if, implements, import, instanceof, int, interface, long, native, new, package, private, protected, public, return, short, static, strictfp, super, switch, synchronized, this, throw, throws, transient, try, void, volatile, while, assert, enum. Это полный список. Назвав переменную одним из этих слов, вы прогневаете богов программ:)

А ещё будет совсем зашибенно, если вы будете давать переменным осмысленные имена. Так будет проще разобраться в коде, да и читать его будет приятнее и удобнее:)

Ещё есть такая вещь, как область видимости переменных в коде. Одно определение. Блок кода - одна или несколько строк кода, заключенные в фигурные скобки {}. Помните, я говорил, что если переменная определена в цикле, после его отработки она будет недоступна? Так вот, такое бывает не только в циклах, а в любых внутренних блоках кода - те переменные, что определены во внутренних блоках кода, недоступны во внешних. А вот если определить переменную во внешнем блоке, например, в теле самого метода, то она будет доступна и во внешних блоках, и во внутренних. Пример сделаем такой, хоть и несколько притянутый за ухи:)
{

//Внешний блок кода

int extVar;

{

//Внутренний блок кода, здесь доступна extVar, а вот intVar будет доступна после её определения

int intVar;

//Теперь доступна и intVar

}

//Снова внешний блок кода. Здесь переменная intVar недоступна, а extVar - доступна

}

Обещенную программу я напишу чуть позже, бо листинг очень сильно увеличит размер поста, будет просто неудобно читать:)

Вопросы, замечания, дополнения, пожелания, комментарии - пишем в комментарии не стесняемся:)

вверх^ к полной версии понравилось! в evernote
Комментарии (2):
Прочитала, почти ничего не поняла, но вот не лирические отступоения и юмор - так слова ПОЧТИ и не было бы =))
Yuri_Prime 04-12-2013-22:29 удалить
Ответ на комментарий Isida_Morgenstern # Дык, спрашивай, что не понятно:)


Комментарии (2): вверх^

Вы сейчас не можете прокомментировать это сообщение.

Дневник Программирование на Java: от ламера - чайнику. Пост №2.2. Операторы и конструкции. Матерные. | Yuri_Prime - Записки Yuri_Prime | Лента друзей Yuri_Prime / Полная версия Добавить в друзья Страницы: раньше»