\documentclass[j-spec.tex]{subfiles}

\begin{document}
\pagestyle{plain}
\sloppy
\tableofcontents
\section{Специализация: данные и функции}
\subsection{В предыдущем разделе}
\begin{itemize}
\item Краткая история (причины возникновения); 
\item инструментарий, выбор версии; 
\item CLI;
\item структура проекта;
\item документирование; 
\item некоторые интересные способы сборки проектов.
\end{itemize}

\subsection{В этом разделе}
Будет рассмотрен базовый функционал языка, то есть основная встроенная функциональность, такая как  математические операторы, условия, циклы, бинарные операторы. Далее способы хранения и представления данных в Java, и в конце способы манипуляции данными, то есть функции (в терминах языка называющиеся методами).
\begin{itemize}
\item \nom{Метод}{функция в языке программирования, принадлежащая классу};
\item \nom{Типизация}{классификация по типам};
\item \nom{Переполнение}{целочисленное переполнение (англ. integer overflow) — ситуация в компьютерной арифметике, при которой вычисленное в результате операции значение не может быть помещено в тип данных};
\item \nom{Инициализация}{одновременной объявление переменной и присваивание ей значения};
\item \nom{Идентификатор}{идентификатор переменной -- название переменной, по которому возможно получить доступ к области памяти, соответствующей этой переменной};
\item \nom{Typecasting}{преобразование типов переменных в типизированных языках программирования};
\item \nom{Массив}{структура данных, хранящая набор значений в непрерывной области памяти};
\end{itemize}
\subsection{Данные}
\subsubsection{Понятие типов}
Хранение данных в Java осуществляется привычным для программиста образом: в переменных и константах.

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

\begin{frm}
\info Java является языком со \textbf{строгой} (также можно встретить термин «\textbf{сильной}») \textbf{явной} \textbf{статической} типизацией.  
\end{frm}

\begin{itemize}
\item Статическая -- у каждой переменной должен быть тип, и этот тип изменить нельзя. Этому свойству противопоставляется динамическая типизация.
\item Явная -- при создании переменной ей обязательно необходимо присвоить какой-то тип, явно написав это в коде. В более поздних версиях языка (с девятой) стало возможным инициализировать переменные типа \code{var}, обозначающего нужный тип тогда, когда его возможно однозначно вывести из значения справа\footnote{аналог типа \code{auto} в языке C++}. Бывают языки с неявной типизацией, например, Python.
\item Строгая(сильная) -- невозможно смешивать разнотипные данные. С другой стороны, существует, например, JavaScript, в котором запись \code{2 + true} выдаст результат \code{3}.
\end{itemize}

\subsubsection{Антипаттерн «магические числа»}
Почти во всех примерах, которые используются для обучения, можно увидеть так называемый антипаттерн -- плохой стиль для написания кода. Числа, которые находятся справа от оператора присваивания используются в коде без пояснений. Такой антипаттерн называется «магическое число». Магическое, потому что непонятно, что это за число, почему это число именно такое и что будет, если это число изменить.

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

Например, в вашем коде несколько тысяч строк, а какое-то число, скажем, возраст совершеннолетия, число 18, использовалось несколько десятков раз. При использовании приложения в стране, где совершеннолетием считается 21 год вы должны будете перечитывать весь код в поисках магических «18» и исправить их на «21». В этом вопросе будет также важно не запутаться, действительно ли это 18, которые означают совершеннолетие, а не количество карманов в жилетке Анатолия Вассермана\footnote{мы то знаем, что их 26}.

В случае с константой изменить число нужно в одном месте.

\subsection{Примитивные типы данных}
Все данные в Java делятся на две основные категории: примитивные и ссылочные. Таблица \hrf{tab:types} демонстрирует все восемь примитивных типов языка и их размерности. Чтобы отправить на хранение какие-то данные используется оператор присваивания. Присваивание в программировании -- это не тоже самое, что математическое равенство, демонстрирующее тождественность, а полноценная операция.

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

\begin{table}[H]
    \centering
    \begin{tabular}{|p{17mm}|p{80mm}|p{55mm}|}
        \hline
        Тип & Пояснение & Диапазон \\
        \hline
        byte & Самый маленький из адресуемых типов, 8 бит, знаковый & [\textminus128, +127] \\
        \hline
        short & Тип короткого целого числа, 16 бит, знаковый & [\textminus32 768, +32 767]\\
        \hline
        char & Целочисленный тип для хранения символов в кодировке UTF-8, 16 бит, беззнаковый & [0, +65 535]\\
        \hline
        int & Основной тип целого числа, 32 бита, знаковый & [\textminus2 147 483 648, +2 147 483 647] \\
        \hline
        long & Тип длинного целого числа, 64 бита, знаковый & [\textminus9 223 372 036 854 775 808, +9 223 372 036 854 775 807] \\
        \hline
        float & Тип вещественного числа с плавающей запятой (одинарной точности, 32 бита) &  \\
        \hline
        double & Тип вещественного числа с плавающей запятой (двойной точности, 64 бита) &  \\
        \hline
        boolean & Логический тип данных & true, false \\
        \hline
    \end{tabular}
    \caption{Основные типы данных в языке Java}
    \label{tab:types}
\end{table}

\begin{frm}\info
По умолчанию, создавая примитивную переменную, ей из-за примитивности данных, Java присваивает начальное значение -- ноль для числовых и ложь для булева. Что ещё раз доказывает, что мы храним там просто числа в двоичной системе счисления, мы не можем туда положить пустоту, а ноль -- это тоже значение.
\end{frm}

Шесть из восьми типов имеет диапазон значений, а значит основное их отличие в объёме занимаемой памяти. У \code{double} и \code{float} тоже есть диапазоны, но они заключаются в точности представления дробной части. Диапазоны означают, что если попытаться положить в переменную меньшего типа большее значение, произойдёт «переполнение переменной».

\subsubsection{Переполнение целочисленных переменных}
Чем именно чревато переполнение переменной, легче показать на примере (по ссылке --  \href{https://habr.com/ru/company/pvs-studio/blog/306748/}{расследование} крушения ракеты из-за переполнения переменной)

\begin{frm} \excl Переполнение переменных не распознаётся компилятором. \end{frm}

Если создать переменную типа \code{byte}, диапазон которого от $[-128, +127]$, и присвоить этой переменной значение $200$ произойдёт переполнение, как если попытаться влить пакет молока в напёрсток.

\begin{frm} \info Переполнение переменной -- это ситуация, в которой происходит попытка положить большее значение в переменную меньшего типа. \end{frm}

Важным вопросом при переполнении остаётся следующий: какое в переполненной переменной останется значение? Максимальное, $127$? $200 - 127 = 73$? Какой-то мусор? Каждый язык, а зачастую и разные компиляторы одного языка ведут себя в этом вопросе по разному.

\begin{frm}
  \begin{center}
  \excl В современном мире гигагерцев и терабайтов почти никто не пользуется маленькими типами, но именно из-за этого ошибки переполнения переменных становятся опаснее испанской инквизиции.

    \includegraphics[width=5cm]{jc-02-spanish.jpg}
  \end{center}
\end{frm}

\subsubsection{Задание для самопроверки}
\begin{enumerate}
\item Возможно ли объявить в Java целочисленную переменную и присвоить ей дробное значение?
\item Магическое число -- это:
  \begin{enumerate}
  \item числовая константа без пояснений;
  \item число, помогающее в вычислениях;
  \item числовая константа, присваиваемая при объявлении переменной.
  \end{enumerate}
\item Переполнение переменной -- это:
  \begin{enumerate}
  \item слишком длинное название переменной;
  \item слишком большое значение переменной;
  \item расширение переменной вследствие записи большого значения.
  \end{enumerate}
\end{enumerate}

\subsubsection{Бинарное (битовое) представление данных}
После информации о переполнении, нельзя не сказать о том, что именно переполняется. Далее будут представлены сведения которые касаются не только языка Java но и любого другого языка программирования. Эти сведения помогут разобраться в деталях того как хранится значение переменной в программе и как, в целом, происходит работа компьютерной техники.

\begin{frm} \info Все современные компьютеры, так или иначе работают от электричества и являются примитивными по своей сути устройствами, которые понимают только два состояния: есть напряжение в электрической цепи или нет. Эти два состояния принято записывать в виде 1 и 0, соответственно. \end{frm}

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

\begin{table}[H]
    \centering
    \begin{tabular}{|r|r|r|r|}
      \hline
      Десятичное & Двоичное & Восьмеричное & Шестнадцатеричное\\
      \hline
      00 & 00000 & 00 & 0x00 \\
      01 & 00001 & 01 & 0x01 \\
      02 & 00010 & 02 & 0x02 \\
      03 & 00011 & 03 & 0x03 \\
      04 & 00100 & 04 & 0x04 \\
      05 & 00101 & 05 & 0x05 \\
      06 & 00110 & 06 & 0x06 \\
      07 & 00111 & 07 & 0x07 \\
      08 & 01000 & 10 & 0x08 \\
      09 & 01001 & 11 & 0x09 \\
      10 & 01010 & 12 & 0x0a \\
      11 & 01011 & 13 & 0x0b \\
      12 & 01100 & 14 & 0x0c \\
      13 & 01101 & 15 & 0x0d \\
      14 & 01110 & 16 & 0x0e \\
      15 & 01111 & 17 & 0x0f \\
      16 & 10000 & 20 & 0x10 \\
      \hline
    \end{tabular}
    \caption{Представления чисел}
    \label{tab:counting-systems}
\end{table}

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

\begin{frm}
\info Одна единица или ноль -- это один \textbf{бит} передаваемой или хранимой информации.
\end{frm}

Биты принято собирать в группы по восемь штук, по восемь разрядов, эти группы называются \textbf{байт}. В языке Java возможно оперировать минимальной единицей информации, такой как байт для этого есть соответствующий тип. Диапазон байта, согласно таблицы $[-128, +127]$, то есть байт информации может в себе содержать ровно 256 значений. Само число $127$ в двоичной записи это семиразрядное число, все разряды которого единицы (то есть байт выглядит как \code{01111111}). Последний, восьмой, самый старший бит, определяет знак числа\footnote{Для более детального понимания данной темы желательно ознакомиться с информацией о цифровой схемотехнике и хранении отрицательных чисел с применением техники дополнительного кода.}. Для нас достаточно знать формулу расчёта записи отрицательных значений:
\begin{enumerate}
\item в прямой записи поменять все нули на единицы и единицы на нули;
\item поставить старший бит в единицу.
\end{enumerate}
Так возможно получить на единицу меньшее отрицательное число, то есть преобразовав 0 получим -1, 1 будет -2, 2 станет -3 и так далее.

Числа б\'{о}льших разрядностей могут хранить б\'{о}льшие значения, таким образом, преобразование диапазонов из десятичной системы счисления в двоичную покажет что \code{byte} это один байт, \code{short} это два байта, то есть 16 бит, \code{int} это 4 байта то есть 32 бита, а \code{long} это 8 байт или 64 бита хранения информации.

\subsubsection{Задания для самопроверки}
\begin{enumerate}
\item Возможно ли число 3000000000 (три миллиарда) записать в двоичном представлении?
\item Как вы думаете, почему шестнадцатеричная система счисления вытеснила восьмеричную?
\end{enumerate}

\subsubsection{Целочисленные типы}
Целочисленных типов четыре, и они занимают 1, 2, 4 и 8 байт.
\begin{frm}
\info Технически, целочисленых типов пять, но \code{char} устроен чуть сложнее других, поэтому не рассматривается в этом разделе.
\end{frm}

Значения в целочисленных типах могут быть только целые, никак и никогда невозможно присвоить им дробных значений. Про эти типы следует помнить следующее:
\begin{itemize}
\item \code{int} -- это самый часто используемый тип. Если сомневаетесь, какой целочисленный тип использовать, используйте \code{int};
\item все целые числа, которые пишутся в коде -- это \code{int}, даже если вы пытаетесь их присвоить переменной другого типа.
\end{itemize}

Как \code{int} преобразуется в меньше типы? Если написать цифрами \textit{справа} число, которое может поместиться в переменную меньшего типа \textit{слева}, то статический анализатор кода его пропустит, а компилятор преобразует в меньший тип автоматически (строка 9 на рис. \hrf{pic:byte-overflow}).
\begin{figure}[H]
  \centering
  \includegraphics[width=12cm]{jc-02-byte-overflow.png}
  \caption{Присваивание валидных и переполняющих значений}
  \label{pic:byte-overflow}
\end{figure}

Как видно, к маленькому \code{byte} успешно присваивается \code{int}. Если же написать число которое больше типа слева и, соответственно, поместиться не может, среда разработки выдает предупреждение компилятора, что ожидался \code{byte}, а передан \code{int} (строка 10 рис. \hrf{pic:byte-overflow}).

Часто нужно записать в виде числа какое-то значение большее чем может принимать \code{int}, и явно присвоить начальное значение переменной типа \code{long}.

\begin{figure}[H]
  \centering
  \includegraphics[width=12cm]{jc-02-int-overflow.png}
  \caption{Попытка инициализации переменной типа \code{long}}
  \label{pic:int-overflow}
\end{figure}

В примере на рис. \hrf{pic:int-overflow} показана попытка присвоить значение 5000000000 (пять миллиардов) переменной типа \code{long}. Из текста ошибки ясно, что невозможно положить такое большое значение в переменную типа \code{int}, а это значит, что справа \code{int}. Почему большой \code{int} без проблем присваивается к маленькому байту?

\begin{figure}[H]
  \centering
  \includegraphics[width=12cm]{jc-02-float-overflow.png}
  \caption{Решение проблемы переполнения числовых констант}
  \label{pic:overflow-solution}
\end{figure}

На рис. \hrf{pic:overflow-solution} продемонстрировано, что аналогичная ситуация возникает с типами \code{float} и \code{double}. Все дробные числа, написанные в коде -- это \code{double}, поэтому положить их во \code{float} без дополнительных усилий невозможно. В этих случаях к написанному справа числу нужно добавить явное указание на его тип.

\begin{frm}\excl
Для \code{long} пишем \code{L}, а для \code{float} -- \code{f}. Чаще всего \code{L} пишут заглавную, чтобы подчеркнуть, что тип больше, а \code{f} пишут маленькую, чтобы подчеркнуть, что мы уменьшаем тип. Но регистр в этом конкретном случае значения не имеет, можно писать и так и так.
\end{frm}

\subsubsection{Числа с плавающей запятой (точкой)}
Как видно из таблицы \hrf{tab:types}, два из восьми типов не имеют диапазонов значений. Это связано с тем, что диапазоны значений \code{float} и \code{double} заключаются не в величине возможных хранимых чисел, а в точности этих чисел после запятой.

\begin{frm} \info Числа с плавающей запятой в англоязычной литературе называются числа с плавающей точкой (от англ. floating point). Такое различие связано с тем, что в русскоязычной литературе принято отделять дробную часть числа запятой, а в европейской и американской -- точкой. \end{frm}

Хранение чисел с плавающей запятой\footnote{хорошо и подробно, но на С, в посте на \href{https://habr.com/ru/post/112953/}{Хабре}.} работает по стандарту IEEE 754 (1985 г). Для работы с числами с плавающей запятой на аппаратурном уровне к обычному процессору добавляют математический сопроцессор (FPU, floating point unit).

\begin{figure}[H]
  \centering
  \begin{subfigure}[b]{0.48\textwidth}
    \centering
    \def\svgwidth{\textwidth}
    \includesvg{pics/jc-02-float-struct.svg}
    \caption{double}
    \label{pic:float-double}
  \end{subfigure}
  \hfill
  \begin{subfigure}[b]{0.48\textwidth}
    \centering
    \def\svgwidth{\textwidth}
    \includesvg{pics/jc-02-float-struct32.svg}
    \caption{float}
    \label{pic:float-float}
  \end{subfigure}
  \caption{Типы с плавающей запятой}
  \label{pic:float-struct}
\end{figure}

Рисунок \hrf{pic:float-struct} демонстрирует, как распределяются биты в числах с плавающей запятой разных разрядностей, где S -- Sign (знак), E -- Exponent, 8 (или 11) разрядов поля порядка, экспонента, M -- Mantissa, 23 (или 52) бита мантиссы, дробная часть числа. Также на рисунке показана так называемая, мнимая единица, она всегда есть в самом старшем разряде мантиссы, поэтому её всегда подразумевают, но в явном виде не хранят, экономя один бит информации.

Если попытаться уложить весь стандарт в два предложения, то получится примерно следующее: получить число в соответствующих разрядностях возможно по формулам:
\begin{equation*}
  \begin{gathered}
 F_{32} = (-1)^S \times 2^{E-127} \times (1 + \frac{M}{2^{23}}) \\
 F_{64} = (-1)^S \times 2^{E-1023} \times (1 + \frac{M}{2^{52}})
  \end{gathered}
\end{equation*}

\begin{frm} \info Например:
  $+0,5 = 2^{-1}$ поэтому, число будет записано как

  \code{0_01111110_00000000000000000000000}, то есть знак $= 0$, мантисса $= 0$, порядок = $127 - 1 = 126$, чтобы получить следующие результаты вычислений:

  $-1^0$ положительный знак, умножить на порядок

  $2^{126-127 = -1} = 0,5$ и умножить на мантиссу
  
  $1 + 0$. То есть, $-1^0 \times 2^{-1} \times (1 + 0) = 0,5.$

  Отсюда становится очевидно, что чем сложнее мантисса и чем меньше порядок, тем более точные и интересные числа мы можем получить.
\end{frm}
 
Возьмём для примера число $-0,15625$, чтобы понять как его записывать, откинем знак, это будет единица в разряде, отвечающем за знак, и посчитаем мантиссу с порядком. Представим число как положительное и будем от него последовательно отнимать числа, являющиеся отрицательными степенями двойки, чтобы получить максимально близкое к нулю значение, но не превысить его.

\begin{equation*}
  \begin{gathered}
2^{1} = 2 \\ 2^{0} = 1.0 \\ 2^{-1} = 0.5 \\ 2^{-2} = 0.25 \\ 2^{-3} = 0.125 \\ 2^{-4} = 0.0625 \\ 2^{-5} = 0.03125 \\ 2^{-6} = 0.015625 \\ 2^{-7} = 0.0078125 \\ 2^{-8} = 0.00390625
  \end{gathered}
\end{equation*}

Очевидно, что $-1$ и $-2$ степени отнять не получится, поскольку мы явно уходим за границу нуля, а вот $-3$ прекрасно отнимается, значит порядок будет $127-3 = 124$, осталось понять, что получится в мантиссе.

Видим, что оставшееся после первого вычитания ($0,15625 - 0,125$) число -- это $2^{-5}$. Значит в мантиссе пишем \code{01} и остальные нули, то есть слева направо указываем, какие степени после $-3$ будут нужны. $-4$ не нужна, а $-5$ нужна.

Получится, что
\begin{equation*}
  \begin{gathered}
(-1)^1 \times 2^{(124-127)} \times (1 + \frac{2097152}{2^{23}}) = -0,15625 \\
\text{или, тождественно,}\\    
(-1)^1 \times 1,01e-3 = (-1)^1 \times 1 \times2^{-3} + 0\times2^{-4} + 1\times2^{-5} = \\
(-1)^1 \times 1 \times0,125 + 0\times0,0625 + 1\times0,03125 = 0,125 + 0,03125 = \\
(-1)^1 \times 0,15625 = -0,15625
  \end{gathered}
\end{equation*}

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

\begin{figure}[h]
  \centering
  \includegraphics[width=17cm]{jc-02-float02.png}
  \caption{Особенности работы с числами с плавающей запятой}
  \label{pic:float-points}
\end{figure}

К особенностям работы чисел с плавающей запятой можно отнести:
\begin{itemize}
\item возможен как положительный, так и отрицательный ноль (в целых числах ноль всегда положительный);
\item есть огромная зона, отмеченная на рисунке \hrf{pic:float-points}, которая являет собой непредставимые числа, слишком большие для хранения внутри такой переменной или настолько маленькие, что мнимая единица в мантиссе отсутствует;
\item в таком числе можно хранить значения положительной и отрицательной бесконечности;
\item при работе с такими числами появляется понятие не-числа, при этом важно помнить, что \code{NaN != NaN}.
\end{itemize}

\subsubsection{Задания для самопроверки}
\begin{enumerate}
\item Сколько байт данных занимает самый большой целочисленный тип?
\item Почему нельзя напрямую сравнивать целочисленные данные и числа с плавающей запятой, даже если там точно лежит число без дробной части?
\item Внутри переполненной переменной остаётся значение:
  \begin{enumerate}
  \item переданное -- максимальное для типа;
  \item максимальное для типа;
  \item не определено.
  \end{enumerate}
\end{enumerate}

\subsubsection{Символы и булевы}
Шесть из восьми примитивных типов могут иметь как положительные, так и отрицательные значения, они называются \textbf{«знаковые»} типы. В таблице есть два типа, у которых есть диапазон но нет отрицательных значений, это \code{boolean} и \code{char}

Булев тип хранит значение \code{true} или \code{false}. На собеседованиях иногда спрашивают, сколько места занимает \code{boolean}. В Java объём хранения не определён и зависит от конкретной JVM, обычно считают, что это один байт.

\begin{table}[h!]
  \centering
  \begin{tabular}{||c|c|c||c|c|c||c|c|c||c|c|c||}
    \hline
    dec & hex  & val   & dec & hex  & val               & dec & hex  & val      & dec & hex  & val \\
    \hline
    000 & 0x00 & (nul) & 032 & 0x20 & \textvisiblespace & 064 & 0x40 & @        & 096 & 0x60 & \textquoteleft \\
    001 & 0x01 & (soh) & 033 & 0x21 & !                 & 065 & 0x41 & A        & 097 & 0x61 & a \\ 
    002 & 0x02 & (stx) & 034 & 0x22 & "                 & 066 & 0x42 & B        & 098 & 0x62 & b \\ 
    003 & 0x03 & (etx) & 035 & 0x23 & \#                & 067 & 0x43 & C        & 099 & 0x63 & c \\ 
    004 & 0x04 & (eot) & 036 & 0x24 & \$                & 068 & 0x44 & D        & 100 & 0x64 & d \\ 
    005 & 0x05 & (enq) & 037 & 0x25 & \%                & 069 & 0x45 & E        & 101 & 0x65 & e \\ 
    006 & 0x06 & (ack) & 038 & 0x26 & \&                & 070 & 0x46 & F        & 102 & 0x66 & f \\ 
    007 & 0x07 & (bel) & 039 & 0x27 & \textquotesingle  & 071 & 0x47 & G        & 103 & 0x67 & g \\ 
    008 & 0x08 & (bs)  & 040 & 0x28 & (                 & 072 & 0x48 & H        & 104 & 0x68 & h \\ 
    009 & 0x09 & (tab) & 041 & 0x29 & )                 & 073 & 0x49 & I        & 105 & 0x69 & i \\ 
    010 & 0x0A & (lf)  & 042 & 0x2A & *                 & 074 & 0x4A & J        & 106 & 0x6A & j \\ 
    011 & 0x0B & (vt)  & 043 & 0x2B & +                 & 075 & 0x4B & K        & 107 & 0x6B & k \\ 
    012 & 0x0C & (np)  & 044 & 0x2C & \textquoteright   & 076 & 0x4C & L        & 108 & 0x6C & l \\ 
    013 & 0x0D & (cr)  & 045 & 0x2D & -                 & 077 & 0x4D & M        & 109 & 0x6D & m \\ 
    014 & 0x0E & (so)  & 046 & 0x2E & .                 & 078 & 0x4E & N        & 110 & 0x6E & n \\ 
    015 & 0x0F & (si)  & 047 & 0x2F & /                 & 079 & 0x4F & O        & 111 & 0x6F & o \\ 
    016 & 0x10 & (dle) & 048 & 0x30 & 0                 & 080 & 0x50 & P        & 112 & 0x70 & p \\ 
    017 & 0x11 & (dc1) & 049 & 0x31 & 1                 & 081 & 0x51 & Q        & 113 & 0x71 & q \\ 
    018 & 0x12 & (dc2) & 050 & 0x32 & 2                 & 082 & 0x52 & R        & 114 & 0x72 & r \\ 
    019 & 0x13 & (dc3) & 051 & 0x33 & 3                 & 083 & 0x53 & S        & 115 & 0x73 & s \\ 
    020 & 0x14 & (dc4) & 052 & 0x34 & 4                 & 084 & 0x54 & T        & 116 & 0x74 & t \\ 
    021 & 0x15 & (nak) & 053 & 0x35 & 5                 & 085 & 0x55 & U        & 117 & 0x75 & u \\ 
    022 & 0x16 & (syn) & 054 & 0x36 & 6                 & 086 & 0x56 & V        & 118 & 0x76 & v \\ 
    023 & 0x17 & (etb) & 055 & 0x37 & 7                 & 087 & 0x57 & W        & 119 & 0x77 & w \\ 
    024 & 0x18 & (can) & 056 & 0x38 & 8                 & 088 & 0x58 & X        & 120 & 0x78 & x \\ 
    025 & 0x19 & (em)  & 057 & 0x39 & 9                 & 089 & 0x59 & Y        & 121 & 0x79 & y \\ 
    026 & 0x1A & (eof) & 058 & 0x3A & :                 & 090 & 0x5A & Z        & 122 & 0x7A & z \\ 
    027 & 0x1B & (esc) & 059 & 0x3B & ;                 & 091 & 0x5B & [        & 123 & 0x7B & \char`\{ \\ 
    028 & 0x1C & (fs)  & 060 & 0x3C & <                 & 092 & 0x5C & \char`\\ & 124 & 0x7C & | \\ 
    029 & 0x1D & (gs)  & 061 & 0x3D & =                 & 093 & 0x5D & ]        & 125 & 0x7D & \char`\} \\ 
    030 & 0x1E & (rs)  & 062 & 0x3E & >                 & 094 & 0x5E & \^{}     & 126 & 0x7E & \~{} \\ 
    031 & 0x1F & (us)  & 063 & 0x3F & ?                 & 095 & 0x5F & \char`\_ & 127 & 0x7F & \code{\DEL} \\ 
    \hline
  \end{tabular}
  \caption{Фрагмент UTF-8 (ASCII) таблицы}
  \label{table:utf-8-ascii}
\end{table}
 
Тип \code{char} единственный беззнаковый целочисленный тип в языке, то есть его старший разряд хранит полезное значение, а не признак положительности. Тип целочисленный но по умолчанию среда исполнения интерпретирует его как символ по таблице utf-8 (см. фрагмент в таблице \hrf{table:utf-8-ascii}).

\begin{frm}\excl
  В языке Java есть разница между одинарными и двойными кавычками.
\end{frm}

В одинарных кавычках всегда записывается символ (\code{char}), который на самом деле является целочисленным значением, а в двойных кавычках всегда записывается строка, которая фактически является экземпляром класса \code{String}. Поскольку типизация строгая, то невозможно записать в \code{char} строки, а в строки числа.

\begin{frm} \info В Java есть три основных понятия, связанных с данными переменными и использованием значений: объявление, присваивание, инициализация.

  Для того чтобы \textit{объявить} переменную, нужно написать её тип и название, также часто вместо названия можно встретить термин идентификатор.

  Далее в любой момент можно \textit{присвоить} этой переменной значение, то есть необходимо написать идентификатор, использовать оператор присваивания, и справа написать значение, которое вы хотите присвоить данной переменной. Поставить в конце строки точку с запятой.

  Также существует понятие \textit{инициализации} -- это когда объединяются на одной строке объявление и присваивание.\end{frm}

\subsubsection{Преобразование типов}
Java - это язык со строгой статической типизацией, но преобразование типов в ней всё равно есть. Простыми словами, преобразование типов -- это когда компилятор видит, что типы переменных по разные стороны присваивания разные, начинает разрешать это противоречие, успешно или нет. Преобразование типов бывает явное и неявное. Неявное преобразование типов происходит когда компилятор в состоянии сам преобразовать типы, явное, когда ему нужна помощь.

\begin{frm}
\info В разговоре или в сообществах можно услышать или прочитать термины тайпкастинг, кастинг, каст, кастануть, и другие производные от английского typecasting.
\end{frm}

Неявное преобразование типов происходит, когда присваиваются числа переменным меньшей размерности, чем \code{int}. Число справа это \code{int}, а значит 32 разряда, а слева, например, \code{byte}, и в нём всего 8 разрядов, но ни среда ни компилятор не «поругались», потому что значение в большом \code{int} не превысило 8 разрядов маленького \code{byte}. Итак неявное преобразование типов происходит в случаях, когда, «всё и так понятно». В случае, если неявное преобразование невозможно, статический анализатор кода выдаёт ошибку, что ожидался один тип, а был дан другой.

Явное преобразование типов происходит, когда мы явно пишем в коде, что некоторое значение должно иметь определённый тип. Этот вариант приведения типов тоже был рассмотрен, когда к числам дописывались типовые квалификаторы \code{L} и \code{f}. Но чаще всего случается, что происходит присваивание переменным не тех значений, которые были написаны в тексте программы, а те, которые получились в результате каких-то вычислений.
\begin{figure}[H]
  \centering
  \includegraphics[width=12cm]{jc-02-byte-cast-error.png}
  \caption{Ошибка приведения типов}
  \label{pic:byte-cast-error}
\end{figure}

На рис. \hrf{pic:byte-cast-error} приведён простейший пример, в котором очевидно, что внутри переменной \code{i0} содержится значение, не превышающее одного байта хранения, а значит возможно явно сообщить компилятору, что значение точно поместится в \code{byte}. \textit{Явно преобразовать типы}. Для этого нужно в правой части оператора присваивания перед идентификатором переменной в скобках добавить название типа, к которому необходимо преобразовать значение этой переменной.
\begin{figure}[H]
  \centering
  \includegraphics[width=12cm]{jc-02-byte-cast-fix.png}
  \caption{Верное приведение типов}
  \label{pic:byte-cast-error}
\end{figure}

\subsubsection{Константность}
Constare -- (лат. стоять твёрдо). Константность это свойство неизменяемости. В Java ключевое слово \code{const} не реализовано, хоть и входит в список ключевых, зарезервированных. Константы создаются при помощи ключевого слова \code{final}. Ключевое слово \code{final} возможно применять не только с примитивами, но и со ссылочными типами, методами, классами.

\begin{frm}
\info Константа -- это переменная или идентификатор с конечным значением.
\end{frm}

\subsubsection{Задания для самопроверки}
\begin{enumerate}
\item Какая таблица перекодировки используется для представления символов?
\item Каких действий требует от программиста явное преобразование типов?
\item какое значение будет содержаться в переменной a после выполнения строки \code{int а = 10.0f/3.0f;}
\end{enumerate}

\subsection{Ссылочные типы данных, массивы}
Ссылочные типы данных -- это все типы данных, кроме восьми перечисленных примитивных. Самым простым из ссылочных типов является массив. Фактически, массив выведен на уровень языка и не имеет специального ключевого слова.

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

\begin{frm} \info \textbf{Массив} -- это единая, сплошная область данных, в связи с чем в массивах возможно осуществление доступа по индексу \end{frm}

Самый младший индекс любого массива -- \textit{ноль}, поскольку \textbf{индекс} -- это значение смещения по элементам относительно начального адреса массива. То есть, для получения самого первого элемента нужно сместиться на ноль шагов. Очевидно, что самый последний элемент в массиве из десяти значений, будет храниться по \textit{девятому} индексу.

Массивы возможно создавать несколькими способами (листинг \hrf{lst:array-init}). В общем виде объявление -- это тип, квадратные скобки как обозначение того, что это будет массив из переменных этого типа, идентификатор (строка \hrf{codeline:arr-define}). Инициализировать массив можно либо ссылкой на другой массив (строка \hrf{codeline:arr-link}), пустым массивом (строка \hrf{codeline:arr-new}) или заранее заданными значениями, записанными через запятую в фигурных скобках (строка \hrf{codeline:arr-values}). Присвоить в процессе работы  идентификатору возможно только значение ссылки из другого идентификатора или новый пустой массив.

\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Объявление массива},label={lst:array-init}]
  int[] array0;<@ \label{codeline:arr-define} @>
  int[] array1 = array0;<@ \label{codeline:arr-link} @>
  int[] array2 = new int[5];<@ \label{codeline:arr-new} @>
  int[] array3 = {5, 4, 3, 2, 1};<@ \label{codeline:arr-values} @>

  array2 = {1, 2, 3, 4, 5}; // <@\lh{dkgreen}{<-- здесь недопустимо присваивание}@> <@ \label{codeline:arr-invalid} @>
\end{lstlisting}

Если мы не определяем переменную, понятно, данные мы хранить не планируем. Если определяем примитивную, помним, она инициализируется нулём, а если мы определяем ссылочный идентификатор, он имеет начальное значение \code{null}, то есть явно демонстрирует, что не ссылается ни на какой объект. \textbf{Нулевой указатель} -- это гораздо более серьёзное явление, чем просто временное отсутствие объекта по идентификатору, очень часто это не инициализированные объекты и попытки вызова невозможных методов. Поэтому в работе очень часто помогает понять, что именно пошло не так \code{NullPointerException}.

\begin{frm} \excl Никак и никогда нельзя присвоить идентификатору целый готовый массив (создаваемый здесь и сейчас) в процессе работы, нельзя стандартными средствами переприсвоить ряд значений части массива (так называемые слайсы или срезы). \end{frm}

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

Ключевое слово \code{final} работает только с идентификатором массива, то есть не запрещает изменять значения его элементов.

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

Прочитать из массива значение возможно обратившись к ячейке массива по индексу. Записать в массив значение возможно обратившись к ячейке массива по индексу, и применив оператор присваивания.
\begin{lstlisting}[language=Java,style=JCodeStyle]
  int i = array[0];
  array[1] = 10;
\end{lstlisting}

В каждом объекте массива есть специальное поле (рис. \hrf{pic:array-length}), которое обозначает длину данного массива. Поле находится в классе \code{__Array__} и является публичной константой.

\begin{figure}[H]
  \centering
  \includegraphics[width=12cm]{jc-02-array-length.png}
  \caption{Константа с длиной массива}
  \label{pic:array-length}
\end{figure}

\subsubsection{Задания для самопроверки}
\begin{enumerate}
\item Почему индексация массива начинается с нуля?
\item Какой индекс будет последним в массиве из 100 элементов?
\item Сколько будет создано одномерных массивов при инициализации массива 3х3?
\end{enumerate}

\subsection{Базовый функционал языка}
\subsubsection{Математические операторы}
Математические операторы работают как и предполагается -- складывают, вычитают, делят, умножают, делают это по приоритетам, известным нам с пятого класса, а если приоритет одинаков -- слева направо. Специального оператора возведения в степень как в Python нет. Единственное, что следует помнить, что оператор присваивания продолжает быть оператором присваивания, а не является математическим тождеством, а значит сначала посчитается всё, что слева, а потом результат попробует присвоиться переменной справа. Припоминаем какие есть особенности у операции целочисленного деления, связанные с отбрасыванием дробной части.

\subsubsection{Условия}
Условия представлены в языке привычными \code{if}, \code{else if}, \code{else}, «если», «иначе если», «в противном случае», которые являются единым оператором выбора, то есть, если исполнение программы пошло по одной из веток, то в другую ветку условия программа никогда не зайдёт. Каждая ветвь условного оператора -- это отдельный кодовый блок со своим окружением и локальными переменными.

Существует альтернатива оператору \code{else if} -- использование оператора \code{switch}, который позволяет осуществлять множественный выбор между числовыми значениями. У оператора есть ряд особенностей:
\begin{itemize}
\item это оператор, состоящий из одного кодового блока, то есть сегменты кода находятся в одной области видимости. Если не использовать оператор \code{break}, есть риск «проваливаться» в следующие кейсы;
\item нельзя создать диапазон значений;
\item достаточно сложно создавать локальные переменные с одинаковым названием для каждого кейса.
\end{itemize}

\subsubsection{Циклы}
Циклы представлены основными конструкциями:
\begin{itemize}
\item \code{while () {}}
\item \code{do {} while();}
\item \code{for (;;) {}}
\end{itemize}

Цикл -- это набор повторяющихся до наступления условия действий. \code{while} -- самый простой, чаще всего используется, когда нужно описать бесконечный цикл. \code{do-while} единственный цикл с постусловием, то есть сначала выполняется тело, а затем принимается решение о необходимости зацикливания, используется для ожидания ответов на запрос и возможного повторения запроса по условию. \code{for} -- классический счётный цикл, его почему-то программисты любят больше всего.

Существует также активно пропагандируемый цикл -- \code{foreach}, работает не совсем очевидным образом, для понимания его работы необходимо ознакомиться с ООП и понятием итератора.

\subsubsection{Бинарные арифметические операторы}
В современных реалиях мегамощных компьютеров вряд ли кто-то задумывается об оптимизации скорости выполнения программы или экономии занимаемой памяти. Но всё меняется, когда программист впервые принимает сложное решение: запрограммировать микроконтроллер или другой «интернет вещей». Там в вашем распоряжении пара сотен килобайт памяти, если очень повезёт, в которые нужно не только как-то вложить текст программы и исполняемый бинарный код, но и какие-то промежуточные, пользовательские и другие данные, буферы обмена и обработки. Другая ситуация, в которой нужно начинать «думать о занимаемом пространстве» это разработка протоколов передачи данных, чтобы протокол был быстрый, не передавал по сети большие объёмы данных и быстро преобразовывался. На помощь приходит натуральная для информатики система счисления, двоичная.

Манипуляции двоичными данными представлены в Джава следующими операторами:
\begin{itemize}
\item \code{&} битовое и;
\item \code{|} битовое или;
\item \code{~} битовое не;
\item \code{^} исключающее или;
\item \code{<<} сдвиг влево;
\item \code{>>} сдвиг вправо.
\end{itemize}

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

\begin{frm} \info В Java в литеральных операциях может участвовать только тип \code{boolean}, в то время, как, например, C++ воспринимает любой ненулевой целочисленный литерал как истину, а нулевой, соответственно, как ложь.
\end{frm}

Логика формирования значения при этом остаётся такой же, как и при битовых операциях.

\begin{table}[h!]
  \centering
  \begin{tabular}{||c|c|c||} 
    \hline
    A & B & AND \\ [0.5ex] 
    \hline\hline
    0 & 0 & 0 \\ 
    0 & 1 & 0 \\
    1 & 0 & 0 \\
    1 & 1 & 1 \\
    \hline
  \end{tabular}
  \hfill
  \begin{tabular}{||c|c|c||} 
    \hline
    A & B & OR \\ [0.5ex] 
    \hline\hline
    0 & 0 & 0 \\ 
    0 & 1 & 1 \\
    1 & 0 & 1 \\
    1 & 1 & 1 \\
    \hline
  \end{tabular}
  \hfill
  \begin{tabular}{||c|c|c||} 
    \hline
    A & B & XOR \\ [0.5ex] 
    \hline\hline
    0 & 0 & 0 \\ 
    0 & 1 & 1 \\
    1 & 0 & 1 \\
    1 & 1 & 0 \\
    \hline
  \end{tabular}
  \hfill
  \begin{tabular}{||c|c||} 
    \hline
    A & NOT \\ [0.5ex] 
    \hline\hline
    0 & 1 \\
    1 & 0 \\
    \hline
  \end{tabular}
  \caption{Таблицы истинности битовых операторов}
  \label{table:bin-truth-tables}
\end{table}

Когда говорят о битовых операциях, так или иначе, появляется необходимость поговорить о таблицах истинности. В таблице \hrf{table:bin-truth-tables} вы видите таблицы истинности для арифметических битовых операций. Битовые операции отличаются тем, что для неподготовленного взгляда они производят почти магические действия, потому что манипулируют двоичным представлением числа.

\begin{figure}[H]
  \begin{arithmetic}
    00000100&4\\
    \code{&} 00000111&7\\
    00000100&4\\
  \end{arithmetic}
  \hfill
  \begin{arithmetic}
    00000100&4\\
    \code{|} 00000111&7\\
    00000111&7\\
  \end{arithmetic}
  \hfill
  \begin{arithmetic}
    00000100&4\\
    \code{^} 00000111&7\\
    00000011&3\\
  \end{arithmetic}
  \hfill
  \begin{arithmetic}
    \code{~} 00000100&4\\
    11111011&-5\\
  \end{arithmetic}
  \caption{Бинарная арифметика}
  \label{fig:bit-ops}
\end{figure}

\begin{table}[h!]
  \centering
  \begin{tabular}{||c|c|c||} 
    \hline
    Число & Бинарное & Сдвиг \\ [0.5ex] 
    \hline\hline
  2 & 00000010 & \code{2 << 0} \\
  4 & 00000100 & \code{2 << 1} \\
  8 & 00001000 & \code{2 << 2} \\
 16 & 00010000 & \code{2 << 3} \\
 32 & 00100000 & \code{2 << 4} \\
 64 & 01000000 & \code{2 << 5} \\
    128 & 10000000 & \code{2 << 6} \\
    \hline
  \end{tabular}
    \begin{tabular}{||c|c|c||} 
    \hline
    Число & Бинарное & Сдвиг \\ [0.5ex] 
    \hline\hline
    128 & 10000000 & \code{128 >> 0} \\
 64 & 01000000 & \code{128 >> 1} \\
 32 & 00100000 & \code{128 >> 2} \\
 16 & 00010000 & \code{128 >> 3} \\
  8 & 00001000 & \code{128 >> 4} \\
  4 & 00000100 & \code{128 >> 5} \\
  2 & 00000010 & \code{128 >> 6} \\
    \hline
  \end{tabular}
  \caption{Битовые сдвиги}
  \label{table:bit-shift}
\end{table}

С битовыми сдвигами работать гораздо интереснее и выгоднее. Они производят арифметический сдвиг значения слева на количество разрядов, указанное справа, в таблице \hrf{table:bit-shift} представлены восьмиразрядные беззнаковые числа, в битовом представлении это одна единственная единица, находящаяся в разных разрядах числа. Это демонстрация сдвига на один разряд влево, и, как следствие, умножение на два. Обратная ситуация со сдвигом вправо, он является целочисленным делением.

\begin{frm} \info
  \begin{itemize}
  \item \code{X && Y} -- литеральная;
  \item \code{X || Y} -- литеральная;
  \item \code{!X} -- литеральная;
  \item \code{N << K} -- $N * 2^K$;
  \item \code{N >> K} -- $N / 2^K$;
  \item \code{x & y} -- битовая. 1 если оба x = 1 и y = 1;
  \item \code{x | y} -- битовая. 1 если хотя бы один из x = 1 или y = 1;
  \item \code{~x} -- битовая. 1 если x = 0;
  \item \code{x ^ y} -- битовая. 1 если x отличается от y.
  \end{itemize}
\end{frm}

\subsubsection{Задания для самопроверки}
\begin{enumerate}
\item Почему нежелательно использовать оператор \code{switch} если нужно проверить диапазон значений?
\item Возможно ли записать бесконечный цикл с помощью оператора \code{for}?
\item \code{2 + 2 * 2 == 2 << 2 >> 1}?
\end{enumerate}

\subsection{Функции}
\textbf{Функция} -- это исполняемый блок кода. Функция, принадлежащая классу называется \textbf{методом}.

\begin{lstlisting}[language=Java,style=JCodeStyle]
  void method(int param1, int param2) {
      //function body
  }

  public static void main (String[] args) {
      method(arg1, arg2);
  }
\end{lstlisting}

При объявлении функции в круглых скобках указываются параметры, а при вызове -- аргументы.

У функций есть правила именования: функция -- это переходный глагол совершенного вида в настоящем времени (вернуть, посчитать, установить, создать), часто снабжаемый дополнением, субъектом действия. Методы в Java пишутся lowerCamelCase. Важно, в каком порядке записаны параметры метода, от этого будет зависеть порядок передачи в неё аргументов. Методы обособлены и их параметры локальны, то есть не видны другим функциям.
\begin{frm}
\excl Нельзя писать функции внутри других функций.
\end{frm}

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

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

Возвращаемого значения у метода может и не быть, в некоторых языках такие функции и методы называются процедурами, а в Java для них просто придумали специальное возвращаемое значение -- \code{void}. Void (от англ. пустота), интересно отметить, что это не какое-то простое emptyness, а серьёзное масштабное космическое void, чтобы подчеркнуть, что метод совсем ничего точно не возвращает.

\textbf{Вызов метода} -- это, по смыслу, тоже самое, что подставить в код сразу его возвращаемое значение.

\textbf{Сигнатура метода} -- это имя метода и его параметры. В сигнатуру метода не входит возвращаемое значение. Нельзя написать два метода с одинаковой сигнатурой.

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

\subsection*{Практическое задание}
\begin{enumerate}
\item Написать метод «Шифр Цезаря», с булевым параметром зашифрования и расшифрования и числовым ключом;
\item Написать метод, принимающий на вход массив чисел и параметр n. Метод должен осуществить циклический (последний элемент при сдвиге становится первым) сдвиг всех элементов массива на n позиций;
\item Написать метод, которому можно передать в качестве аргумента массив, состоящий строго из единиц и нулей (целые числа типа \code{int}). Метод должен заменить единицы в массиве на нули, а нули на единицы и не содержать ветвлений. Написать как можно больше вариантов метода.
\end{enumerate}

\newpage
\printnomenclature[40mm]

\end{document}
