Данные

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

1. Данные внутри программы

С одной стороны здесь все очевидно — программа должна работать с данными. И внутри программы данные должны быть. С другой стороны — все очень непросто. Данные сами по себе могут иметь достаточно сложную структуру. Например, мы хотим написать программу для расчета движения тела с заданной скоростью из какой-то точки на плоскости в другую. В данном случае нам будет достаточно ввести координаты X и Y, время T и скорость V. Далее мы сможем использовать несложные формулы для расчетов и хранения наших данных для последующего вывода (формулы предлагается взять из учебника физики или математики). Но если тело будет не одно, а 5 или 10 ? Или в общем случае нам заранее неизвестно сколько тел мы будет обсчитывать. Тогда нам потребуется более сложная структура данных. Было бы здорово, чтобы для описания состояния одного тела мы могли вы выделить какую-то группу данных, а потом объединили их в еще какую-то структуру для хранения. Например структуру BODY содержала бы нужные нам X,Y,V, а структура ALL_BODY содержала бы список структур BODY. Как видим, само построение структур данных задача не всегда тривиальная. Очень интересная книга по данным и алгоритмам их обработки была написана Никлаусом Виртом — «Алгоритмы и структуры данных». Можете поискать в интернете. Но скорее всего прочитать сразу все вы не сможете — книга несколько академична. Но тем не менее ее можно и нужно посмотреть.
Важно понять один момент — ДАННЫЕ НЕ ОГРАНИЧИВАЮТСЯ ПРОСТЫМИ ВЕЩЕСТВЕННЫМИ ЧИСЛАМИ. Например, данные о гражданине может включать в себя достаточно много полей — имя, фамилия, отчество, дата рождения, паспортные данные и многое другое. И эти данные надо уметь организовывать в удобные для обработки структуры — по таким структурам удобно осуществлять поиск, их удобно отображать, хранить. С их помощью удобно добавлять, редактировать, удалять, работать с целыми группами.
Организация данных весьма важный вопрос. На мой взгляд, именно при решении задач организации данных появилось объектно-ориентированное программирование, о котором пойдет речь при изучении Java.

2. Внешние данные

Внешние данные — это данные, которые находятся где-то вне программы. С помощью уже готовых программ (подпрограмм, пакетов, технологий) эти данные можно получить внутрь нашей программы. Стоит обратить внимание, что внешние данные все равно придется для начала разместить во внутренних данных. И только потом ими можно будет пользоваться. Давайте более подробно остановимся на том, откуда же можно брать данные. Ответ на этот вопрос дает нам список тех технологий (пакетов, подпрограмм), которые используются в современных языках программирования (в том числе и в Java). Итак:

2.1 Файлы

Достаточно очевидное хранилище данных. Наверняка многие из вас создавали документы в программе «Блокнот», MS Word, Excel и многих других. Каждый документ сохраняется в файле. Это и есть наши внешние данные. Совсем необязательно, что ваши файлы будут содержать столь сложные структуры, как документ в формате Word, но тем не менее нахождение данных в файле — важный момент.

2.2 Внешние программы

Внешние программы — это не только программы, которые запущены на Вашем компьютере — это программы, которые запущены на других компьютерах (хотя может быть и на том же самом — но это ДРУГИЕ программы). В эру сети Интернет взаимодействие программ становится очень важным элементом и возможности взаимодействия программ необходимо изучать. Разумеется в Java и в других современных языках есть целый ряд технологий, позволяющих осуществлять такое взаимодействие.

2.3 Базы данных

Если быть точным, то работа с базами данных может быть включена как в раздел «Файлы», так и в раздел «Внешние программы». Базы данных могут быть организованы в виде простых файлов или в виде специальной программы, которая обрабатывает внешние запросы от других программ (такая организация сегодня является наиболее предпочтительной даже в случае, если база данных используется локально).

Переменные и типы данных в Java

Зачем нужны переменные ?

На самом деле это достаточно важный вопрос. Большинство современных программистов не очень задумываются, насколько важным является введение переменных. Когда алгоритмических языков не было, программистам надо было думать не только над тем, как обрабатывать данные — надо было думать над тем, где эти данные хранить. Перед программистом был просто кусок памяти, внутри которого можно и нужно было разместить команды и данные. Каждое число, символ или строку надо было разместить в ячейках памяти по определенному адресу. Что было кропотливой и достаточно скучной работой.
Мало того — надо было еще помнить, какого типа данные лежат в той или иной ячейке. Потому как хранить целое или вещественное число надо было по-разному. И обрабатывать тоже по-разному. Чтобы не делать эту малоинтересную работу постоянно, в алгоритмических языках появилось такое понятие — переменная. При компиляции программ каждая переменная (со своим именем) размещается в определенных ячейках и ее обработка зависит от ее типа. Причем соблюдение этих правил берет на себя программа/компилятор, а программист может сосредоточиться на более интересных вещах.
Это, на мой взгляд, было здорово — программист теперь не думал, где и как хранить данные. Он просто ОБЪЯВЛЯЛ переменную нужного типа. И в дальнейшем в программе обращался к ней по имени. А выделение памяти под нее, правильность ее обработки брал на себя компилятор.
И теперь программисту надо было сделать только одно — объявить переменную с нужным типом. На самом деле есть языки, где этого делать не надо, но на мой взгляд, это хорошо работает в небольших программах. Сам по себе очень неоднозначный вопрос и много копий было сломано и немало «священных войн» (holy war — холивар) можно найти на просторах Интернет по этому поводу.

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

<тип> имя;

Имя переменной в Java включает следующие символы — латинские буквы (большие и маленькие), цифры, знак доллара «$» и знак подчеркивания «_». Имя не должно начинаться с цифры. Длина имени имеет ограничения, но такую длины вы скорее всего использовать не будете — речь идет об очень больших величинах.

Таким образом корректными будут следующие имена:

Данные в Java условно можно разделить на два больших раздела:

  1. Элементарные типы данных
  2. Сложные типы данных — классы

 

Элементарные типы данных

Элементарными типами являются следующие:

  • целые числа
  • вещественные числа
  • единичные символы
  • булевы или логические типы

 

Целые числа — это обычные целые числа. Но внутри Java их несколько.

  • byte — число от -128 до 127 (длина 1 байт)
  • short — число от -32,768 до 32,767 (длина 2 байта)
  • int — число от -2,147,483,648 до 2,147,483,647 (длина 4 байта)
  • long — число от -9,223,372,036,854,775,808 до +9,223,372,036,854,775,807 (длина 8 байт)

 

Вещественные числа — это числа с десятичной дробью.

  • float — число от 1.40129846432481707e-45 до 3.40282346638528860e+38 (длина 4 байта)
  • double — число от 4.94065645841246544e-324d до 1.79769313486231570e+308d (длина 8 байт)

Вещественное число можно записывать в форме с десятичной точкой. Например так:

Также число может быть записано со степенью десяти. Например 1.4 на 10 в степени 5 можно записать так:

Или так

Как видите, можно писать «e» или «E». Число перед «E» называется мантисса, после — показатель степени числа 10
Здесь надо учесть, что из-за ограничений по длине при сложении чисел с большой положительной степенью (например +40) и очень большой отрицательно (например -60) маленькое число будет просто утеряно — на него просто не хватит разрядов в мантиссе (это 1.40129..). Т.е. количество чисел после запятой ограничено и младшие разряды просто не учитываются. Для учета таких ситуаций были разрабтаны специальные программы для суммирования массивов чисел — сначала складывались самые маленькие, чтобы накопить хоть какое-то значимое число, потом прибавлялись все больше и больше.

 

Символ
char — символ (длина 2 байта — для возможности использовать Unicode)
Символ записывается в одиночных кавычках. Например

Также символ может быть записан в цифровой форме. Здесь надо учесть, что для символа используется два байта. Например, символ ‘A’ можно записать в виде ‘\ u0041’. Символ ‘1’ — ‘\u0031’. Но число записывается не в десятичном, а в шестнадцатиричном коде. Таким образом можно использовать непечатные символы.

 

Логическое значение
boolean — может принимать всего два значение — true или false

Т.е. если я хочу объявить переменную типа int с именем counter, то это будет выглядеть так:

int counter;

Вещественное (double) с именем bigCounter так:

double bigCounter;

ВАЖНОЕ ЗАМЕЧАНИЕ:
Размер данных строго фиксирован — для любой реализации Java (под любую операционную систему) размер элементарных переменных всегда один и тот же. Что отличает Java от того же Си — там не все типы имеют точный размер.

Операторы

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

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

Наверно это самый популярный и важный оператор. С его помощью можно в переменную поместить нужное значение. Записывается он в виде знака «=». Давайте сразу напишем несложную программу — файл Second.java.

И теперь разберем те строки, которые находятся под строкой

Я не хочу сейчас долго и муторно вам объяснять то, что находится выше — давайте пока ограничимся тем, что наша программа начинается так, как она начинается. У нее есть верхняя часть

Пока единственное, на что следует обратить внимание — это то, что слово, которое стоит после public class должно быть такое же, как и имя у файла (но без расширения .java). В нашем случае это Second. Придет время и мы постараемся разобраться со всеми этими словами. Но потихонечку.

Также есть часть, которую мы как раз и будем рассматривать — внутри фигурных скобок после строки public static void main(String[] arg) {. В ближайшее время все наше внимание будет именно здесь.

И заключительная часть (две закрывающие фигурные скобки)

Ну что же, поехали. Первая строка — объявляем переменную целого типа с именем «counter».

int counter;

Вторая строка — присваивание переменной counter значения 99.

counter = 99;

И наконец третья строка выводит значение переменной counter на экран

System.out.println(counter);

Думаю, что самое время обратить ваше внимание на еще один момент — практически каждая команда на языке Java обычно заканчивается знаком «;» (точка с запятой). Этот символ используется в подавляющем количестве языков как указание на окончание команды. Дальше мы будем так часто использовать этот символ, что вы станете его использовать автоматически. (Это будет несомненно полезным навыком).
Мало того — вы можете использовать символ ; без оператора вообще. Это так называемый «пустой оператор». Например вот так (обратите внимание, что файл теперь должен называться SecondEmpty.java)

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

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

Предлагаю вам самостоятельно сделать полный цикл — редактирование, компилирование, запуск. Закрепите недавно приобретенные знания.

 

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

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

1. Сложение — «+»
Например, сложить два числа и присвоить результат третьему.

2. Вычитание — «-«
Например:

3. Умножение — «*»
Например:

4. Деление — «/»
Например:

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

Результат будет : 2. На самом деле все логично — 12 помещается в 34 два раза. И остаток от деления получится 10.
Если погрузиться чуть глубже, то дело заключается в следующем — компилятор приводит все выражение справа от оператора присваивания к самому «вместительному» типу. Т.е. если бы мы делили double 34 на int 12, то получили бы 2.833333333.

Обратите внимание на то, что нам придется и переменную «c» тоже объявить как double. Это необходимо, чтобы компилятор мог поместить «самый вместительный» тип (а он у нас double) в переменную для хранения результата.

5. Остаток от деления — «%»
Остаток от деления имеет смысл при делении целых чисел. Например, программа

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

Вы догадались, что файл должен называться Fourth.java ?

 

Изменение значения переменной

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

Конструкции, подобные этой настолько часто встречаются, что в Java были введены специальные операторы.

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

Оба оператора соответствуют конструкции

Но между первым и вторым существует одна разница, которую я продемонстрирую на примере. Обратите внимание на название AddOneFirst и AddOneSecond — именно так должны называться ваши файлы с текстом программ.

Результат

Результат

Как видим место расположения оператора ++ влияет на результат. В первом случае мы СНАЧАЛА ПРИСВОИЛИ переменной «a» значение из переменной «x» и только потом увеличили «x».
Во втором случае мы СНАЧАЛА УВЕЛИЧИЛИ переменную «x» а потом присвоили ее значение переменной «a».
Если вы задумаетесь о сдаче сертификата — там много коварных вопросов связанных с этим оператором. Попробуйте угадать результат следующих операторов:

 

Операция сложения для символов

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

Логические операции

Тип boolean на самом деле достаточно удобный для решения многих задач. Для него определены следующие операции:

1. Логическое сложение — «||»
В сложении если хоть одно слагаемое равно true, то результат тоже true. Например:

В переменной f3 результат равен true.

2. Логическое умножение — «&&»
В умножении если хоть одно слагаемое равно false, то результат тоже false. Например:

В переменной f3 результат равен false.

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

3. Операция отрицания — «!»
Например:

Переменная b получит значение false.

 

Укороченное вычисление логических операций

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

Здесь можно видеть, что для вычисления переменной «d» совсем необязательно вычислять все — операция || указывает, что в данном случае достаточно того, что переменная «a» равна «true». Все остальное можно не вычислять. Т.к. первая часть в операторе ИЛИ дает нам TRUE, то зачем проверять (вычислять) вторую часть ? Там может быть что угодно, но результат все равно уже гарантировано будет TRUE. Это и есть принцип укороченного вычисления. Но иногда такое вычисление необходимо. Давайте снова рассмотрим пример. (Я очень хочу, чтобы вы читали код и понимали его — это очень полезный навык).
Так вот попробуйте угадать, какое значение переменной «b» будет выведено ?

Если вы подумали, что 0 — вы правильно подумали. Именно так — т.к. переменная «a» определяет заранее результат, то часть (++b > 0) даже не проверяется. Существует возможность заставить все-таки вычислять и вторую часть. Для этого надо использовать вместо «||» выражение «|». Смотрим пример:

Здесь выражение для вычисления переменной «result» выглядит немного иначе. И результат уже будет … 1. Точно такое же выражение можно использовать в случае «&&».
Насколько этот вариант вам будет подходить — смотрите сами. Лично я стараюсь не использовать такие конструкции — они могут запутать. Но иногда это удобно.

 

Комментарии

В любой программе есть код, который достаточно сложно понять. Для того, чтобы можно было вставить пояснения используются комментарии. В Java комментарии можно записывать двумя способами.
1. С помощью конструкции в виде двух символов «/*» для начала комментария и «*/» для окончания. Такая конструкция позволяет писать многострочные комментарии. Например:

2. Однострочный комментарий
Однострочные комментарии начинаются со строки «//» и длятся до конца строки.

Отмечу один момент — пишите осмысленные комментарии. Не пишите после строки a = 10; комментарий типа «в переменную a помещаем число 10». Совершенно бесмысленна трата времени и пространства — это прекрасно видно из кода.

 

Мы познакомились с элементарными типами данных, посмотрели какие операции над ними можно производить. Знакомоство с классами мы отложим на некторое время. А сейчас самое время познакомится с конструкциями для управления порядком выполнения операций. Управление порядком выполнения операций