This commit is contained in:
Ivan I. Ovchinnikov 2022-12-20 23:51:19 +03:00
parent 818b2c05bb
commit 44bd7a1313
13 changed files with 903 additions and 90 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,6 +1,7 @@
\documentclass[j-spec.tex]{subfiles}
\begin{document}
\pagestyle{plain}
\tableofcontents
\section{Платформа: история и окружение}
\subsection{В этом разделе}

View File

@ -3,6 +3,7 @@
\begin{document}
%\setcounter{tocdepth}{3}
\setcounter{section}{1}
\pagestyle{plain}
\tableofcontents
\section{Специализация: данные и функции}
\subsection{В предыдущем разделе}
@ -681,17 +682,14 @@ Constare - (лат. стоять твёрдо). Константность эт
\textbf{Перегрузка методов} - это механизм языка, позволяющий написать методы с одинаковыми названиями и разными оставшимися частями сигнатуры, чтобы получить единообразие при вызове семантически схожих методов с разнотипными данными.
\subsection{Практическое задание}
\subsection*{Практическое задание}
\begin{enumerate}
\item Написать метод «Шифр Цезаря», с булевым параметром зашифрования и расшифрования и числовым ключом;
\item Написать метод, принимающий на вход массив чисел и параметр n. Метод должен осуществить циклический (последний элемент при сдвиге становится первым) сдвиг всех элементов массива на n позиций;
\item Написать метод, которому можно передать в качестве аргумента массив, состоящий строго из единиц и нулей (целые числа типа \code{int}). Метод должен заменить единицы в массиве на нули, а нули на единицы и не содержать ветвлений. Написать как можно больше вариантов метода.
\end{enumerate}
% \subsection*{Задания к семинару}
% \begin{itemize}
% \item Сравнить без условий две даты, представленные в виде трёх чисел гггг-мм-дд;
% \end{itemize}
\newpage
\printnomenclature[40mm]
\end{document}

View File

@ -18,6 +18,15 @@
\item \nom{Вложенный класс}{статический класс, объявленный внутри другого класса.};
\item \nom{Локальный класс}{класс, объявленный внутри минимального блока кода другого класса, чаще всего, метода.};
\item \nom{Исключение}{это отступление от общего правила, несоответствие обычному порядку вещей.};
\item \nom{Искл. (событие)}{поведение потока исполнения (например, программы), пользователя или аппаратурного окружения, приведшее к исключению. При возникновении исключения создаётся объект исключения и работа потока останавливается.};
\item \nom{Искл. (объект)}{созданный программным кодом или JRE объект, передаваемый от потока, в котором произошло исключительное событие, обработчику исключений};
\item \nom{Обработчик искл.}{объект, работающий в потоке error или его наследники, способный ловить объекты исключений и совершать с ними манипуляции, например, выводить информацию об объекте исключения в консоль.};
\item \nom{\code{throw}}{оператор, активирующий (выбрасывающий) объект исключения.};
\item \nom{Stacktrace}{часть объекта исключения, содержащая максимальное количество информации об иерархии методов, вызовы которых привели к исключительной ситуации.};
\item \nom{\code{try...catch}}{двухсекционный оператор языка Java, позволяющий «безопасно» выполнить код, содержащий исключение, поймать и обработать возникшее исключение.};
\item \nom{\code{throws}}{ключевое слово, определяющее обработку исключения в методе. Фактически, это предупреждение для вызывающего о возможном исключении в методе.};
\item \nom{\code{finally}}{часть оператора \code{try...catch}, выполняющаяся вне зависимости от того, возникло ли исключение в секции \code{try} и было ли оно обработано в секции \code{catch}.};
\item \nom{Подавленное искл.}{исключение, возникшее \textit{первым} в ситуации, когда в одном операторе \code{try...catch...finally} выброшены исключения как в \code{try}, так и в \code{finally}.};
\item \nom{Многопоточность}{одновременное выполнение двух или более потоков для максимального использования центрального процессора (CPU -- central processing unit). Каждый поток работает параллельно и имеет свою собственную выделенную стековую память.};
\end{itemize}
@ -334,6 +343,7 @@ voice.sayMur();
\end{enumerate}
\subsection{Исключения}
\subsubsection{Понятие}
Язык программирования -- это, в первую очередь, набор инструментов. Например, есть художник. У художника есть набор всевозможных красок, кистей, холстов, карандашей, мольберт, ластик и прочие. Это всё его инструменты. Тоже самое для программиста. У программиста есть язык программирования, который предоставляет ему инструменты: циклы, условия, классы, функции, методы, ООП, фрейморки, библиотеки. Исключения -- это один из инструментов. Исключения всегда следует рассматривать как ещё один инструмент для работы программиста.
\begin{frm} \info Исключение -- это отступление от общего правила, несоответствие обычному порядку вещей
@ -346,6 +356,7 @@ voice.sayMur();
\item ошибка в аппаратной части компьютера?
\end{itemize}
\subsubsection{Общие сведения}
При возникновении ошибок создаётся объект класса «исключение», и в этот объект записывается какое-то максимальное количество информации о том, какая ошибка произошла, чтобы потом прочитать и понять, где проблема. Соответственно эти объекты возможно «ловить и обрабатывать».
\begin{figure}[H]
@ -355,136 +366,359 @@ voice.sayMur();
\label{pic:exception-hierarchy}
\end{figure}
Все исключения наследуются от класса \code{Throwable} и могут быть как обязательные к обработке, так и необязательные. Есть ещё подкласс \code{Error}, но он больше относится к аппаратным сбоям или серьёзным алгоритмическим или архитектурным ошибкам, и на данном этапе интереса не представляет, потому что поймав, например, \code{OutOfMemoryError} средствами Java прямо в программе с ним ничего сделать невозможно, такие ошибки необходимо обрабатывать и не допускать в процессе разработки ПО.
Для изучения и примеров, воспользуемся двумя подклассами \code{Throwable} -- \code{Exception} -- \code{RuntimeException} и \code{IOException}.
\begin{frm} \excl Все исключения, кроме наследников \code{RuntimeException} необходимо обрабатывать.
\begin{frm} \excl Все исключения (\textbf{checked}), кроме наследников \code{RuntimeException} (\textbf{unchecked}), необходимо обрабатывать.
\end{frm}
% лайвкод 04-мартёшка-методов & Давайте рассмотрим примерчики, напишем пару-тройку методов, и сделаем матрёшку,
Опишем на простом примере, один метод вызывает другой, второй вызывает третий и последний всё портит:
% из мэйна вызываем метод2, оттуда метод1, оттуда метод0, а в методе0 всё как всегда портим, пишем
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Цепочка методов},label={lst:except-div-1}]
private static int div0(int a, int b) {
return a / b;
}
% private static int div0() return 1 / 0;
private static int div1(int a, int b) {
return div0(a, b);
}
% ArithmeticException является наследником класса RuntimeEcxeption поэтому статический анализатор его не подчеркнул, и ловить его вроде как не обязательно, спасибо большое разработчикам джава, надёжность кода не повысилась, единообразность работы всех исключений нарушилась, всё хорошо.\\ \hline
private static int div2(int a, int b) {
return div1(a, b);
}
\end{lstlisting}
% лайвкод 04-метод-деления & Выходит, на примере деления на ноль можно всё хорошо сразу и объяснить. допустим у нас есть какой-то метод который возможно мы даже сами написали, который, скажем, целочисленно делит два целых числа. немного его абстрагируем
% private static int div0(int a, int b) return a / b;
\begin{figure}[H]
\centering
\includegraphics[width=\textwidth]{jc-04-stacktrace-sample.png}
\caption{Результат запуска цепочки методов (листинг \hrf{lst:except-div-1})}
\label{pic:result-except-div-1}
\end{figure}
% Если посмотреть на этот метод с точки зрения программирования, он написан очень хорошо - алгоритм понятен, метод с единственной ответственностью, всё супер. Однако, из поставленной перед методом задачи очевидно, что он не может работать при всех возможных входных значениях. То есть если у нас вторая переменная равна нулю, то это неправильно. И что же с этим делать? \\ \hline
\code{ArithmeticException} является наследником класса \code{RuntimeEcxeption} поэтому статический анализатор кода его не подчеркнул, и «ловить» его не обязательно.
% лайвкод 04-исключение-1 & Нам нужно как-то запретить пользователю передавать в качестве делителя ноль. Самое простое - ничего не делать, но мы так не можем.
При работе с исключениями часто можно встретить слова, похожие на сленг, но это не так. Чаще всего, то, что звучит как сленг -- просто перевод ключевых слов языка, осуществляющих то или иное действие.
\begin{itemize}
\item try -- (англ. пробовать) пробовать, пытаться;
\item catch -- (англ. ловить) ловить, поймать, хватать;
\item throw -- (англ. бросать) выбрасывать, бросать, кидать;
\item NullPointerException -- НПЕ, налпоинтер;
\item и другие...
\end{itemize}
% private static int div0(int a, int b)
% if (b != 0) return a / b; return ???;
Если посмотреть на метод \code{div0(int a, int b)} с точки зрения программирования, он написан очень хорошо -- алгоритм понятен, метод с единственной ответственностью, однако, из поставленной перед методом задачи очевидно, что он не может работать при всех возможных входных значениях. То есть если вторая переменная равна нулю, то это ошибка. Необходимо запретить пользователю передавать в качестве делителя ноль. Самое простое -- ничего не делать, но в программе на языке Java так нельзя, если мы объявили, что метод имеет возвращающее значение, он обязан что-то вернуть.
% Потому что метод должен что-то вернуть, а что вернуть, неизвестно, ведь от нас ожидают результат деления. Поэтому, допустим можем руками сделать проверку (б == 0ф) и выкинуть пользователю так называемый объект исключения throw new RuntimeException("деление на ноль") а иначе вернём а / б.
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Ошибка -- нельзя ничего не возвращать},label={lst:except-div-error}]
private static int div0(int a, int b) {
if (b != 0)
return a / b;
return ???; // <@\lh{dkgreen}{ошибка}@>
}
\end{lstlisting}
% private static int div0(int a, int b)
% if (b == 0) throw new RuntimeException("parameter error");
% return a / b; \\ \hline
А что вернуть, неизвестно, ведь от метода ожидается результат деления. Поэтому, возможно руками сделать проверку \code{(b == 0f)} и «выбросить» пользователю так называемый \textbf{объект исключения} с текстом ошибки, объясняющим произошедшее, а иначе вернём \code{a / b}.
% лайвкод 04-исключение-2 & Вызываем метод и пробуем делить 1 на 2. А вот если мы второй параметр передадим 0 то у нас выкинется исключение,
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Цепочка методов},label={lst:except-div-better}]
private static int div0(int a, int b) {
if (b == 0f)
throw new RuntimeException("parameter error");
return a / b;
}
\end{lstlisting}
% System.out.println(div0(1,2));
% System.out.println(div0(1,0));
Следовательно, если делитель не равен нулю произойдёт обычное деление, а если равен -- будет «выброшено» исключение.
\begin{figure}[H]
\centering
\includegraphics[width=\textwidth]{jc-04-stacktrace-better.png}
\caption{Исключение, выброшенное «на наших условиях» (листинг \hrf{lst:except-div-better})}
\label{pic:result-except-div-better}
\end{figure}
% то есть по сути new... это конструктор, нового объекта какого-то класса, в который мы передаём какой то параметр, в данном конкретном случае это строка с сообщением. Зафиксируем пока что эту мысль. \\ \hline
Очевидно, что ключевое слово \code{new} вызывает конструктор, нового объекта какого-то класса, в который передаётся какой-то параметр, в данном конкретном случае это строка с сообщением.
% отбивка введение в многопоточность & Кажется многовато отступлений, но без этого точно никак нельзя продолжать. \\ \hline
\subsubsection{Объект исключения}
Ключевое слово \code{throw} заставляет созданный объект исключения начать свой путь по родительским методам, пока этот объект не встретится с каким-то обработчиком. В данном конкретном случае -- это обработчик виртуальной машины (по-умолчанию), который в специальный поток error выводит так называемый stacktrace, и завершает дальнейшее выполнение метода (технически, всего потока целиком).
% 04-метод-броска & Итак, что происходит? Ключевое слово throw заставляет созданный объект исключения начать свой путь по родительским методам, пока этот объект не встретится с каким-то обработчиком. в нашем текущем случае - это дефолтный обработчик виртуальной машины, который в специальный поток err выводит так называемый стектрейс, и завершает дальнейшее выполнение метода.\\ \hline
\begin{figure}[H]
\fontsize{12}{1}\selectfont
\includesvg[scale=1.01]{pics/jc-04-threading.svg}
\caption{Принципиальная схема работы приложения}
\label{pic:throw-treading}
\end{figure}
% 04-поток-ерр & Далее по порядку: поток ерр. Все программы в джава всегда многопоточны. Понимаете вы многопоточность или нет, знаете ли вы о её существовании или нет, не важно, многопоточность есть всегда. не будем вдаваться в сложности прикладной многопоточности, у нас ещё будет на это довольно много времени, пока что поговорим в общем. в чём смысл? смысл в том, что на старте программы запускаются так называемые потоки, которые работают псевдопараллельно и предназначены каждый для решения своих собственных задач, например, это основной поток, поток сборки мусора, поток обработчика ошибок, потоки графического интерфейса. Основная задача этих потоков - делать своё дело и иногда обмениваться информацией.\\ \hline
Все программы в Java всегда многопоточны. На старте программы запускаются так называемые потоки, которые работают псевдопараллельно и предназначены каждый для решения своих собственных задач, например, это основной поток, поток сборки мусора, поток обработчика ошибок, потоки графического интерфейса. Основная задача этих потоков -- делать своё дело и иногда обмениваться информацией.
% 04-стектрейс & В упомянутый же парой минут ранее стектрейс кладётся максимальная информация о типе исключения, его сообщении, иерархии методов, вызовы которых привели к исключительной ситуации. Если не научиться читать стектрейс, если честно, можно расходиться по домам и не думать о серьёзном большом программировании. Итак стектрейс. Когда у нас случается исключение - мы видим, что случилось оно в потоке мэйн, и является объектом класса RuntimeException сообщение мы тоже предусмотрительно приложили. Первое что важно понять, что исключение - это объект класса. Далее читаем матрёшку - в каком методе создался этот объект, на какой строке, в каком классе. Далее смотрим кто вызвал этот метод, на какой строке, в каком классе. Это вообще самый простой стектрейс, который может быть. Бывают полотна по несколько десятков строк, клянусь, сам видел. Особенно важно научиться читать стектрейс разработчикам андроид, потому что именно такие стектрейсы будут вам прилетать в отчёт. У пользователя что то упало, он нажал на кнопку отправить отчёт, и вам в консоль разработчика прилетел стектрейс, который будет являться единственной доступной информацией о том, где вы или пользователь накосячили.\\ \hline
В \textbf{stacktrace}, содержащийся в объекте исключения, кладётся максимальное количество информации о типе исключения, его сообщении, иерархии методов, вызовы которых привели к исключительной ситуации.
% лайвкод 04-простой-пример-исключения & Если мы не напишем никакого исключения, кстати, оно всё равно произойдёт. Это общее поведение исключения. Оно где-то случается, прекращает выполнение текущего метода, и начинает лететь по стеку вызовов вверх. Возможно даже долетит до дефолтного обработчика, как в этом примере.
\begin{frm} \info Важно научиться читать stacktrace на как можно более раннем этапе изучения программирования.
\end{frm}
% int[] arr = {1};
% System.out.println(arr[2])
Итак стектрейс. В стектрейсе на рис. \hrf{pic:result-except-div-better} видно, что исключение было создано в потоке main, и является объектом класса \code{RuntimeException}, сообщение также было предусмотрительно приложено автором кода. Важно понять, что исключение -- это объект класса. Далее, можно просто читать последовательно строку за строкой -- в каком методе создался этот объект, на какой строке, в каком классе. Далее видно, какой код вызвал этот метод, на какой строке, в каком классе.
% Некоторые исключения генерятся нами, некоторые самой джавой, они вполне стандартные, например выход за пределы массива, деление на ноль, и классический нуль-поинтер. \\ \hline
Если не написать явного выбрасывания никакого исключения, оно всё равно будет выброшено. Это общее поведение исключения. Оно где-то случается, прекращает выполнение текущего метода, и начинает лететь по стеку вызовов вверх. Возможно даже долетит до обработчика по-умолчанию. Некоторые исключения создаются в коде явно, некоторые самой Java, они вполне стандартные, например выход за пределы массива, деление на ноль, и классический \code{NullPointer}.
% лайвкод 04-объект-исключения & Посмотрим на исключения под немного другим углом. Создадим какой-нибудь учебный класс, psvm и создадим экземпляр класса исключения
Создадим экземпляр класса исключения внутри метода, вызываемого из \code{main}:
% RuntimeException e = new RuntimeException();
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Инициализация объекта исключения},label={lst:except-init}]
RuntimeException e = new RuntimeException();
\end{lstlisting}
% Если просто сейчас запустить программу, то ничего не произойдёт, нам нужно наше исключение, как бы это сказать, активировать, выкинуть, возбудить сгенерировать. Для этого есть ключевое слово
Если оставить программу в таком виде и запустить, то ничего не произойдёт, исключение нужно выкинуть (активировать, возбудить, сгенерировать). Для этого есть ключевое слово
% throw e;
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Выбрасывание объекта исключения},label={lst:except-throw}]
throw e;
\end{lstlisting}
% Запускаем, видим. Компилятор ошибок не обнаружил и всё пропустил, а интерпретатор наткнулся на класс исключения, и написал нам в консоль следующее, в основном потоке программы возникло вот такое исключение в таком пакете в таком классе на такой строке.
% \\ \hline
Компилятор ошибок не обнаружил и всё пропустил, а интерпретатор наткнулся на класс исключения, и написал в консоль, что в основном потоке программы возникло исключение в пакете в классе на такой-то строке. По стэктрейсу возможно проследить что откуда вызвалось и как программа дошла до исключительной ситуации. Возможно также наследоваться от какого-то исключения и создать свой класс исключений.
% лайвкод 04-рантайм-выводы & Усложним создадим паблик стэтик воид методА, выкинем исключение в нём, и вызовем его из мэйна.
\begin{frm} \info Исключения, наследники \code{RuntimeException}, являются \textbf{Unchecked}, то есть не обязательные для обработки на этапе написания кода. \textit{Все остальные} \code{Throwable} -- обязательные для обработки, статический анализатор кода не просто их выделяет, а обязывает их обрабатывать на этапе написания кода. И просто не скомпилирует проект если в коде есть необработанные исключения, также известные как \textbf{Checked}.
\end{frm}
% теперь по вот этому стэктрейсу можем проследить что откуда вызвалось и как мы дошли до исключительной ситуации. Можем в нашем исключении даже написать наше кастомное сообщение и использовать все эти штуки в разработке. Можем унаследоваться от какого-то исключения и создать свой класс исключений, об этом чуть позже, в общем, всё зависит от поставленной задачи. Достаточно гибкая штука эти исключения. Ну и поскольку это рантаймэксепшн то обрабатывать его на этапе написания кода не обязательно, компилятор на него не ругается, всё круто. \\ \hline
\subsubsection{Обработка}
\begin{frm} \excl Первое, и самое важное, что нужно понять -- почему что-то пошло (или пойдёт) «не так», поэтому не пытайтесь что-то ловить, пока не поймёте что именно произошло, от этого понимания будет зависеть \textit{способ} ловли.
\end{frm}
% 04-иерархия-исключений & На самом деле на этом интересные особенности обработки исключений наследников Runtime, также называемых анчекд заканчивается далее будет гораздо интереснее рассматривать исключения обязательные для обработки, потому что статический анализатор кода не просто их выделяет, а обязывает их обрабатывать на этапе написания кода. И просто не скомпилирует проект если в коде есть необработанные так или иначе исключения также известные как чекд. Заменим Runtime исключение на обычное обязательное к обработке. ((удалить слово Runtime))\\ \hline
Исключение ловится двухсекционным оператором \textbf{\code{try...catch}}, а именно, его первой секцией \code{try}. Это секция, в которой предполагается возникновение исключения, и предполагается, что его возможно обработать. А в секции \code{catch} пишется имя класса исключения, которое будет поймано ловим, и имя объекта (идентификатор), через который внутри секции можно к пойманному объекту обращаться. Секция \code{catch} ловит указанное исключение и \textit{всех его наследников}.
% 04-пробуй-лови & Давайте наше исключение ловить. Первое, и самое важное, что надо понять - это почему что-то упало, поэтому не пытайтесь что то ловить, пока не поймёте что именно произошло, от этого понимания будет зависеть способ ловли. Исключение ловится двухсекционным оператором try-catch, а именно, его первой секцией try. Это секция, в которой предполагается возникновение исключения, и предполагается, что мы можем его поймать. А в секции catch пишем имя класса исключения, которое мы ловим, и имя объекта, в который мы положим экземпляр нашего исключения. Секция catch ловит указанное исключение и всех его наследников. Это важно. Рекомендуется писать максимально узко направленные секции catch, потому что надо стараться досконально знать как работает ваша программа, и какие исключения она может выбрасывать. Ну и ещё потому что разные исключения могут по-разному обрабатываться, конечно-же. Секций catch может быть сколько угодно много. Как только мы обработали объект исключения, он уничтожается, дальше он не поднимается, и в следующие catch не попадает. Мы, конечно, можем его же насильно пульнуть выше, ключевым словом throw. \\ \hline
\begin{frm} \info Рекомендуется писать максимально узко направленные секции \code{catch}, потому что надо стараться досконально знать как работает программа, и какие исключения она может выбрасывать. Также, потому что разные исключения могут по-разному обрабатываться.
\end{frm}
% 04-варианты ? & Так вот, когда какой-то наш метод выбрасывает исключение у нас есть два основных пути: вы обязаны либо вынести объявление этого исключения в сигнатуру метода, что будет говорить тем, кто его вызывает о том, что в методе может возникнуть исключение, либо мы это исключение должны непосредственно в методе обработать, иначе у вас ничего не скомпилируется. Примером одного из таких исключений служит ИО это сокращение от инпут-аутпут и генерируется, когда, вы не поверите, возникает ошибка ввода-вывода. То есть при выполнении программы что-то пошло не так и она, программа не может произвести ввод-вывод в штатном режиме. На деле много чего может пойти не так, операционка заглючила, флешку выдернули, устройство телепортировалось в микроволновку, и всё, случился ИОЭксепшн, не смогла программа прочитать или написать что то в потоке ввода-вывода. Соответственно, уже от этого ИОЭ возникают какие-то другие, вроде FileNotFoundException, которое мы тоже обязаны обработать. Например, мы хотим чтобы наша программа что то там прочитала из файла, а файла на нужном месте не оказалось, и метод чтения генерирует исключение. \\ \hline
Секций \code{catch} может быть любое количество. Как только объект исключения обработан, он уничтожается и в следующие \code{catch} не попадает. Однако, объект возможно явно отправить на обработчик «выше», ключевым словом \code{throw} (чаще всего, используется \code{RuntimeException} с конструктором копирования).
% % +++ Комментатор_Ильнар. Мы вроде нигде про вынос в сигнатуру до этого не говорили, лучше до этих слов сказать что есть второй способ, а то читается так будто мы об этом уже сказали.
Когда какой-то метод выбрасывает исключение у разработчика есть два основных пути:
\begin{itemize}
\item обязанность вынести объявление этого исключения в сигнатуру метода, что будет говорить тем, кто его вызывает о том, что в методе может возникнуть исключение;
\item исключение необходимо непосредственно в методе обработать, иначе ничего не скомпилируется.
\end{itemize}
% 04-ответственность & В случае, если мы выносим объявление исключения в сигнатуру, вызывающий метод должен обработать это исключение точно таким-же образом - либо в вызове, либо вынести в сигнатуру. Исключением из этого правила является класс RuntimeException. Все наследники от него, включая его самого, обрабатывать не обязательно. Туда входит деление на ноль, индексаутофбаунд экзепшн например. то есть те ошибки, которые компилятор пропускает, а возникают они уже в среде исполнения. Обычно уже по названию понятно что случилось, ну и помимо говорящих названий, там ещё содержится много инфы, хотя-бы даже номер строки, вызвавшей исключительную ситуацию. Общее правило работы с исключениями одно - если исключение штатное - его надо сразу обработать, если нет - надо дождаться, пока программа упадёт. Повторю, все исключения надо обрабатывать, примите это как расплату за использование языка Java.\\ \hline
В случае, если объявление исключения выносится в сигнатуру, вызывающий метод должен обработать это исключение точно таким-же образом -- либо в вызове, либо вынести в сигнатуру. Исключением из этого правила является класс \code{RuntimeException}. Все его наследники, включая его самого, обрабатывать не обязательно. Обычно, уже по названию понятно что случилось, и, помимо говорящих названий, там содержится много информации, например, номер строки, вызвавшей исключительную ситуацию.
% лайвкод 04-обработка-вариант-1 & Вернёся к нашему учебному классу и Усложним ещё. в методеА вызовем методБ. а в методеБ выкинем то что нам обязательно надо обработать, например IOE. Вот тут то и начинается веселье. потому что IOE это не наследник рантайм эксепшена, и мы обязаны обрабатывать на этапе компиляции. Тут у нас есть две опции. многим уже известный try-catch, синтаксис его не совсем очевидный, так что тут надо просто сделать усилие и запомнить. пишем
\begin{frm} \info Общее правило работы с исключениями одно -- если исключение штатное -- его надо сразу обработать, если нет -- надо дождаться, пока программа упадёт.
\end{frm}
% try { methodB() } catch (имя класса исключения которое хотим поймать и идентификатор экземпляра) { }.
Общий вид оператора try...catch можно описать следующим образом:
\begin{verbatim}
try {
метод, выбрасывающий исключение
} catch (имя класса исключения и идентификатор) {
команды, обрабатывающие исключение
}
\end{verbatim}
% Если возникло исключение, попадём в кэтч, и тут можем делать что хотим, чтобы программа не упала. Конечно можно написать в кэтч общий класс вроде Throwable или Exception, вспомним про родительские классы, и тогда он поймает вообще все исключения которые могут быть, даже те, которые мы, возможно не ожидаем. Очень часто в процессе разработки нужно сделать, чтобы нам в процессе выполнения что-то конкретное об исключении выводилось на экран, для этого у экземпляра есть метод гетМессадж. Пишем
Если произошло исключение, объект исключения попадает в \code{catch}, и управление ходом выполнения программы попадает в эту секцию. Чаще всего, здесь содержится код, помогающей программе не завершиться. Очень часто в процессе разработки нужно сделать так, чтобы в процессе выполнения что-то конкретное об исключении выводилось на экран, для этого у экземпляра есть метод \code{getMessage()}.
% sout(e.getMessage()).
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Получение сообщения из объекта исключения},label={lst:except-msg}]
System.out.println(e.getMessage());
\end{lstlisting}
% Ещё чаще бывает, что выполнение программы после выбрасывания исключения не имеет смысла и мы хотим чтобы программа упала. Вот тут очень интересный финт придумали. Мы выкидываем новое рантаймэкзепшн, передав в него экземпляр отловленного исключения используя довольно хитрый конструктор копирования. Во как
Ещё чаще бывает, что выполнение программы после выбрасывания исключения не имеет смысла и нужно, чтобы программа завершилась. В этом случае принято выбрасывать новое RuntimeException, передав в него экземпляр пойманного исключения, используя конструктор копирования.
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={«Проброс» исключения на основе пойманного},label={lst:except-rethrow}]
try {
// ...
} catch(Exception e) {
throw new runtimeexception(e);
}
\end{lstlisting}
% catch throw new runtimeexception(e); \\ \hline
\textbf{Второй вариант обработки исключений} -- в сигнатуре метода пишется
% лайвкод 04-обработка-вариант-2 & Второй вариант обработки исключений - мы в сигнатуре метода пишем
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Обработка исключений в сигнатуре},label={lst:except-throws}]
throws IOException,
\end{lstlisting}
% throws IOE,
и, через запятую, все остальные возможные исключения этого метода. После этого, с ним не будет проблем исполнения, но у метода который его вызовет -- появилась необходимость обработать все checked исключения вызываемого. И так далее наверх.
% и через запятую все остальные возможные исключения этого метода. Всё, у нас с ним проблем нет, но у метода который его вызовет - появились. И так далее наверх. Тут всё достаточно просто. Далее пробуем описать какое-то исключение, которое мы обязаны будем ловить. Предлагаю переименовать наш учебный класс и его методы в некоторую имитацию потока ввода-вывода.
\subsubsection{Пример}
Для примера обработки исключений, возникающих на разных этапах работы приложения (жизненного цикла объекта) предлагается описать класс (листинг \hrf{lst:test-stream}), бизнес логика которого подразумевает создание, чтение некоторой информации, например, как если бы нужно было прочитать байт из файла, и закрытие потока чтения, то есть возврат файла обратно под управление ОС.
% Класс ТестСтрим
% методА = конструктор
% методБ = инт читать
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Экспериментальный класс},label={lst:test-stream}]
public class TestStream {
TestStream() {
System.out.println("constructor");
}
int read() {
System.out.println("read");
return 1;
}
public void close() {
System.out.println("close");
}
}
\end{lstlisting}
% Внутри методаБ давайте создадим какой-нибудь FileInputStream который может генерить FileNotFoundException который на самом деле является наследником IOE, который наследуется от Exception. Никаких рантайм, значит обработать мы его обязаны. Два варианта у нас есть, либо мы его укутаем в try-catch, либо вот не можете вы написать обработчик, потому что не знаете как должна обрабатываться данная исключительная ситуация, и обработать её должна сторона, которая вызывает метод чтения, в таком случае пишем, что метод может генерить исключения. Всё, вы теперь свободны от обработки этого исключения в методе чтения. Но теперь подчёркивается метод мейн... и здесь мы встаём перед той-же дилеммой. и так далее по стэку вызовов любой глубины. \\ \hline
То есть, способ работы с объектом данного класса (полностью без ошибок и других нештатных ситуаций) будет иметь следующий вид
% вовочка перед печкой «и так сойдёт» & Важный момент. Задачи бывают разные. Исключения - это инструмент, который нетривиально работает. Важно при написании кода понять, возникающая исключительная ситуация - штатная, или нештатная. В большинстве случаев - ситуации нештатные, поэтому надо уронить приложение и разбираться с тем, что произошло. Допустим для вашего приложения вот стопроцентно какой-то файл должен быть, без него дальше нет смысла продолжать. Что делать, если его нет? Явно не пытаться в него что то писать, правда? Самое плохое, что можно сделать - ничего не делать. Это самое страшное, когда программа повела себя как-то не так, а мы об этом даже не узнали. Допустим мы хотим прочитать файл, вывести в консоль, но мы глотаем исключение, выведя стектрейс куда-то-там какому-то разработчику и наши супер-важные действия не выполнились. Надо ронять. Как ронять? да throw new RuntimeException(e). Крайне редко случаются ситуации, когда исключение надо проглотить. \\ \hline
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Работа в штатном режиме},label={lst:test-stream-main}]
TestStream stream = new TestStream();
int a = stream.read()
stream.close()
\end{lstlisting}
% лайвкод 04-файналли & Давайте обрабатывать дальше. Все помнят, что потоки надо закрывать? Даже если не знали, теперь знаете. Вот, допустим, у нас в нашем модном потоке открылся файл, что то из него прочиталось, потом метод упал с исключением, а файл остался незакрытым, ресурсы заняты. Давайте даже допишем свой класс TestStream пусть его конструктор выбрасывает IOE, метод read выбрасывает IOE и будет метод close, везде будем логировать успешность в read пока оставляем исключение throw new IOE("reading error") в close "closed". Штатно возвращаем из read единичку и логируем, что всё прочитали в мейне. Как всё будет происходить штатно?
Для примера, внутри метода чтения создаётся \code{FileInputStream} который может генерировать обязательный к проверке на этапе написания кода \code{FileNotFoundException}, который является наследником \code{IOException}, который, в свою очередь, наследуется от \code{Exception}.
% TestStream stream = new TestStream();
% int a = stream.read()
% stream.close()
Возникает два варианта: либо обернуть в \code{try...catch}, либо совершенно непонятно, как должна обрабатываться данная исключительная ситуация, и обработать её должна сторона, которая вызывает метод чтения, в таком случае пишется, что метод может выбрасывать исключения. И тогда \code{TestStream} компилируется без проблем, а вот \code{main} скомпилироваться уже не может. В нём нужно оборачивать в \code{try...catch}.
% Далее представим что в методе read что то пошло не так, выбрасываем исключение, и что видим в консоли? создали поток, исключение, конец программы. Что же делать? а делать секцию finally. Секция finally будет выполнена в любом случае, будет исключение, не будет исключения, не важно. Но тут тоже большое спасибо разработчикам джавы, мы не видим наш поток, то есть его надо вынести наружу, а ещё он оказывается не инициализирован, значит надо написать что то типа TestStream stream = null. Теперь всё должно отработать. \\ \hline
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Метод чтения}]
int read() {
FileInputStream s = new FileInputStream("file.txt");
System.out.println("read");
return 1;
}
}
\end{lstlisting}
% лайвкод 04-проблема & Теперь немного неприятностей. Написали мы блок finally, вроде даже избавились от проблемы с закрытием потока. А как быть, если исключение возникло при создании этого потока? Тогда получается, у нас метод закрытия будет пытаться выполниться от ссылки на null. Нехорошо, знаете-ли, получается. Давайте всё сломаем, прям в конструкторе нашего потока выкинем IOE. Получили NPE в блоке finally. Очевидное решение - ставим в секции finally условие, и если поток не равен нулю, закрываем. Вроде клёво. Меняем тактику. Конструктор отрабатывает нормально. Метод чтения всё ещё генерирует исключение, но бац и в методе закрытия что-то пошло не так, и вылетело исключение. Ну вот так не повезло в жизни. Что делаем? Оборачиваем в try-catch. Вроде снова всё классно. Но и тут мы можем наткнуться на неприятность. Допустим, что нам надо в любом случае ронять приложение (в кэтч допишем throw new Runtime...). Тогда если у нас try поймал исключение, и выкинул его, потом finally всё равно выполнится, и второе исключение затрёт первое, мы его не увидим. Ну а поскольку первое для нас важнее, то второе - максимум что мы можем сделать - это залогировать исключение в консольку. Так дела обстояли в седьмой джаве. \\ \hline
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Обработка исключения}]
try {
TestStream stream = new TestStream();
int a = stream.read()
stream.close()
} catch (FileNotFoundException e) {
e.printStackTrace();
}
\end{lstlisting}
% лайвкод 04-с-ресурсами & Что предлагает нам восьмая джава? try-с-ресурсами. Поток - это ресурс, абстрактное понятие. Как с этим работать? Сейчас будет небольшое забегание вперёд, пока что предлагаю просто запомнить магию. Выражаясь строго формально, мы должны реализовать интерфейс Closeable. А что это за интерфейс? (Ctrl+click) там содержится всего один метод close(), который умеет бросать IOE. Напишем везде пока что штатное поведение в нашем тестовом потоке. Залогируем. Далее синтаксис try-с-ресурсами. Все потоки начиная с восьмой джавы реализуют интерфейс Closeable. Стираем все ужасы, которые мы написали, пишем
\begin{frm} \excl Важный момент. Задачи бывают разные. Исключения -- это инструмент, который нетривиально работает. Важно при написании кода понять, возникающая исключительная ситуация -- штатная, или нештатная. В большинстве случаев -- ситуации нештатные, поэтому надо «уронить» приложение и разбираться с тем, что именно произошло. Допустим, для вашего приложения обязательно какой-то файл должен быть, без него дальше нет смысла продолжать. Что делать, если его нет? Ситуация явно нештатная. Самое плохое, что можно сделать -- ничего не делать. Это самое страшное, когда программа повела себя как-то не так, а ни мы, разработчики, ни пользователь об этом даже не узнали. Допустим, мы хотим прочитать файл, вывести в консоль, но мы в обработчике исключения просто выводим стектрейс куда-то, какому-то разработчику в среду разработки, и наши действительно важные действия не выполнились. Надо завершать работу приложения. Как завершать? \code{throw new RuntimeException(e)}. Крайне редко случаются ситуации, когда у исключения достаточно распечатать стектрейс.
\end{frm}
% try(TestStream stream = new TestStream())
% int a = stream.read();
% catch (IOException e)
% new RuntimeException(e)
Потоки ввода-вывода всегда нужно закрывать. Предположим, что в тестовом потоке открылся файл, из него что-то прочитано, потом метод завершился с исключением, а файл остался незакрытым, ресурсы заняты. Дописав класс \code{TestStream} при работе с ним, возвращаем из \code{read} единицу и логируем, что всё прочитали в \code{main}.
% И всё, мы поток не закрываем. За это у нас ответит сама джава. Запустим и проверим. Никаких close() и finally, всё хорошо. Самое классное - если мы ломаем метод read() то трай с ресурсами всё равно наш поток корректно закроет. Иногда вы можете видеть вывод в консоль и стектрейс вразнобой, ничего страшного, просто исключения вылетают в поток error а вывод в консоль в стандартный вывод. Ну и у них иногда случаются асинхронности. А теперь вообще самый смак - ломаем метод закрытия, и джава очень правильно поступит, она выкатит наверх основное исключение, но и выведет "подавленное" исключение, вторичное в стектрейс. По-человечески, красиво, информативно, глаз радуется. Рекомендуется по возможности использовать вот такую конструкцию. Но научиться пользоваться надо и тем и тем, естественно. \\ \hline
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Экспериментальный класс}]
public class TestStream {
TestStream() {
System.out.println("constructor");
}
int read() throws IOException {
throw new IOException("read except");
System.out.println("read");
return 1;
}
public void close() {
System.out.println("close");
}
}
\end{lstlisting}
% % Комментатор_Ильнар. Смотри, многие тут потеряются походу этой лекции про вложенные классы и исключения. Понятно что про ресурс надо объяснить почему без него костылить многие вещи сложно, но многие в этом могут запутаться. Добавь пожалуйста резюме на пальцах после таких блоков. Мол, если уже успели запутаться и потеряться, то вот вам простая инструкция - исключения либо прокидываем, либо обрабатываем. Прокидываем так, обрабатываем в try catch finaly. Есть для обработки прекрасная штука try с ресурсами. для чего все это нужно - можно переслушать то что я рассказал после того как поиграете со всем этим на семинаре. Переслушивать можно медленно и конспектируя несколько раз пока не дойдет, не стесняйтесь это делать. Такое же резюме можно по вложенным классам сделать, чтобы их немного успокоить
Далее представим, что в методе \code{read} что-то пошло не так, выбрасываем исключение, и видим в консоли, что поток создан, произошло исключение, конец программы. Очевидно, поток не закрылся. Что делать?
% 03-наследование & Последнее на сегодня про исключения это наследования и Полиморфизм исключения тема не очень большая и в целом не сложная потому что вы уже знаете что такое класса объекты как классы могут наследоваться и что такое Полиморфизм. Особенно застрять внимание на объектно-ориентированном программирования исключениях скорее всего не нужно потому что было неоднократно сказано что исключение это тоже классы и есть какие-то наследники исключений генерируются и выбрасываю объекты исключений единственное что важно упомянуть это то что под система исключений работает немного не тривиально впрочем это вы могли заметить и сами но мы можем создавать собственные исключения с собственными смыслами и сообщениями и точно также их выбрасывать вместо стандартных наследоваться мы можем от любых исключений единственное что важно это то что не рекомендуется наследоваться от классов throwable и error когда описываете исключение механика checked и unchecked исключений сохраняется при наследование поэтому создав наследник RuntimeException вы получаете не проверяемые на этапе написания кода исключение \\ \hline
Делать секцию \code{finally}. Секция \code{finally} будет выполнена в любом случае, не важно, будет ли поймано секциями \code{catch} какое-то исключение, или нет. Возникает небольшая проблема видимости, объявление идентификатора тестового потока необходимо вынести за пределы секции \code{try}.
% На этом уроке & На этой лекции в дополнение к предыдущей, разобрали такие понятия как внутренние и вложенные классы, было непросто, но мы, кажется, справились; процессы создания, использования и расширения перечислений. Детально разобрали уже знакомое вам понятие исключений и их тесную связь с многопоточностью в джава. Всё время смотрели на исключения с точки зрения ООП, обработали немного исключений, а также раз и навсегда разделили понятия штатных и нештатных ситуаций. \\ \hline
Теперь немного неприятностей. Написанный блок \code{finally}, вроде решает проблему с закрытием потока. А как быть, если исключение возникло при создании этого потока, в конструкторе?
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Проблема в конструкторе}]
public class TestStream {
TestStream() throws IOException {
throw new IOException("construct except");
System.out.println("constructor");
}
int read() throws IOException {
throw new IOException("read except");
System.out.println("read");
return 1;
}
public void close() {
System.out.println("close");
}
}
\end{lstlisting}
Метод закрытия будет пытаться выполниться от ссылки на \code{null}. Недопустимо.
\begin{frm} \info При возникновении в конструкторе потока \code{IOException} - получим \code{NullPointerException} в блоке \code{finally}.
\end{frm}
Очевидное решение -- поставить в секции \code{finally} условие, и если поток не равен \code{null}, закрывать. Это точно сработает. Меняем тактику.
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Проблема при закрытии}]
public class TestStream {
TestStream() throws IOException {
throw new IOException("construct except");
System.out.println("constructor");
}
int read() throws IOException {
throw new IOException("read except");
System.out.println("read");
return 1;
}
public void close() throws IOException {
throw new IOException("close except");
System.out.println("close");
}
}
\end{lstlisting}
Конструктор отрабатывает нормально. Метод чтения всё ещё генерирует исключение, но и в методе закрытия что-то пошло не так, и вылетело исключение. Нужно оборачивать в \code{try...catch}. Итоговый код, работающий с классом будет иметь следующий вид.
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Обработка исключений, насколько это возможно}]
TestStream stream = null;
try {
stream = new TestStream();
int a = stream.read()
stream.close()
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
stream.close();
} catch (NullPointerException e) {
e.printStackTrace();
}
}
\end{lstlisting}
Но и тут возможно наткнуться на неприятность. Допустим, что необходимо в любом случае ронять приложение.
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Проблемы подавленных исключений}]
// ...
catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
stream.close();
} catch (NullPointerException e) {
e.printStackTrace();
}
}
\end{lstlisting}
Тогда если \code{try} поймал исключение, и выкинул его, потом \code{finally} всё равно выполнится, и второе исключение перекроет (подавит) первое, никто его не увидит. Хотя по логике, первое для работы важнее. Так было до Java 1.8.
\subsubsection{try-with-resources block}
Начиная с версии Java 1.8 разработчику предоставляется механизм \textbf{\code{try}-с-ресурсами}. Поток -- это ресурс, абстрактное понятие. Выражаясь строго формально, разработчик должен \textit{реализовать интерфейс} \code{Closeable}. В этом интерфейсе содержится всего один метод \code{close()}, который умеет бросать \code{IOException}. В классе тестового потока нужно всего лишь переопределить этот метод данного интерфейса.
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Реализация интерфейса закрытия потока}]
public class TestStream implements Closeable {
// ...
@Override
public void close() throws IOException {
throw new IOException("close except");
System.out.println("close");
}
}
\end{lstlisting}
Все потоки начиная с Java 1.8 реализуют интерфейс \code{Closeable}. Работа с такими классами имеет лаконичный вид
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Реализация блока try-with-resources}]
try (TestStream stream = new TestStream()) {
int a = stream.read();
} catch (IOException e) {
throw new RuntimeException(e)
}
\end{lstlisting}
В данном коде не нужно закрывать поток явно, это будет сделано автоматически в следствие реализации интерфейса. Если ломается метод \code{read()}, то try-с-ресурсами всё равно корректно закроет поток. При сломанном методе закрытия и сломанном методе чтения одновременно, JVM запишет наверх основное исключение, но и выведет «подавленное» исключение, вторичное в стектрейс. Рекомендуется по возможности всегда использовать try-с-ресурсами.
\subsubsection{Наследование и полиморфизм исключений}
Наследование и полиморфизм для исключений -- тема не очень большая и не сложная, потому что ничего нового в информацию про классы и объекты исключения не привносят. Застрять внимание на объектно-ориентированном программировании в исключениях не целесообразно, потому что исключения это \textit{тоже классы} и те исключения, которые используются в программе -- уже какие-то наследники других исключений.
Генерируются и выбрасываются \textit{объекты исключений}, единственное, что важно упомянуть это то, что подсистема исключений работает не тривиально. Но разработчик может создавать собственные исключения с собственными смыслами и сообщениями и точно также их выбрасывать вместо стандартных. Наследоваться возможно от любых исключений, единственное что важно, это то, что не рекомендуется наследоваться от классов \code{Throwable} и \code{Error}, когда описываете исключение.
Механика checked и unchecked исключений сохраняется при наследовании, поэтому создав наследник \code{RuntimeException} вы получаете не проверяемые на этапе написания кода исключения.
\subsection*{Практическое задание}
\begin{enumerate}

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

580
pics/jc-04-threading.svg Normal file
View File

@ -0,0 +1,580 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="210mm"
height="297mm"
viewBox="0 0 210 297"
version="1.1"
id="svg5"
inkscape:version="1.2.1 (9c6d41e4, 2022-07-14)"
sodipodi:docname="jc-04-threading.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview7"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showgrid="true"
inkscape:zoom="3.8108538"
inkscape:cx="430.61216"
inkscape:cy="261.22755"
inkscape:window-width="1553"
inkscape:window-height="921"
inkscape:window-x="0"
inkscape:window-y="25"
inkscape:window-maximized="0"
inkscape:current-layer="layer1">
<inkscape:grid
type="xygrid"
id="grid1412" />
</sodipodi:namedview>
<defs
id="defs2">
<inkscape:path-effect
effect="spiro"
id="path-effect6491"
is_visible="true"
lpeversion="1" />
<marker
style="overflow:visible"
id="marker3062"
refX="0"
refY="0"
orient="auto-start-reverse"
inkscape:stockid="TriangleStart"
markerWidth="5.3244081"
markerHeight="6.155385"
viewBox="0 0 5.3244081 6.1553851"
inkscape:isstock="true"
inkscape:collect="always"
preserveAspectRatio="xMidYMid">
<path
transform="scale(0.5)"
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
d="M 5.77,0 -2.88,5 V -5 Z"
id="path3060" />
</marker>
<marker
style="overflow:visible"
id="TriangleStart"
refX="0"
refY="0"
orient="auto-start-reverse"
inkscape:stockid="TriangleStart"
markerWidth="5.3244081"
markerHeight="6.155385"
viewBox="0 0 5.3244081 6.1553851"
inkscape:isstock="true"
inkscape:collect="always"
preserveAspectRatio="xMidYMid">
<path
transform="scale(0.5)"
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
d="M 5.77,0 -2.88,5 V -5 Z"
id="path135" />
</marker>
</defs>
<g
inkscape:label="Слой 1"
inkscape:groupmode="layer"
id="layer1">
<text
xml:space="preserve"
style="font-size:4.23333px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;stroke:none;stroke-width:0.264999;stroke-linecap:square;fill-opacity:1"
x="18.520834"
y="76.729164"
id="text2557"><tspan
sodipodi:role="line"
id="tspan2555"
style="stroke-width:0.265;fill:#000000;fill-opacity:1;stroke:none"
x="18.520834"
y="76.729164">main</tspan></text>
<text
xml:space="preserve"
style="font-size:4.23333px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linecap:square"
x="18.520834"
y="71.4375"
id="text2611"><tspan
sodipodi:role="line"
id="tspan2609"
style="stroke-width:0.265"
x="18.520834"
y="71.4375">gc</tspan></text>
<text
xml:space="preserve"
style="font-size:4.23333px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linecap:square"
x="18.520834"
y="66.145836"
id="text2615"><tspan
sodipodi:role="line"
id="tspan2613"
style="stroke-width:0.265"
x="18.520834"
y="66.145836">err</tspan></text>
<text
xml:space="preserve"
style="font-size:4.23333px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linecap:square"
x="18.520834"
y="60.854164"
id="text2619"><tspan
sodipodi:role="line"
id="tspan2617"
style="stroke-width:0.265"
x="18.520834"
y="60.854164">EDT</tspan></text>
<text
xml:space="preserve"
style="font-size:4.23333px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linecap:square"
x="18.520834"
y="55.5625"
id="text2623"><tspan
sodipodi:role="line"
id="tspan2621"
style="stroke-width:0.265"
x="18.520834"
y="55.5625">EventQueue</tspan></text>
<text
xml:space="preserve"
style="font-size:4.23333px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linecap:square"
x="18.520834"
y="50.270836"
id="text2627"><tspan
sodipodi:role="line"
id="tspan2625"
style="stroke-width:0.265"
x="18.520834"
y="50.270836">UserThreads</tspan></text>
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1;marker-start:url(#TriangleStart);marker-end:url(#marker3062)"
d="M 44.979167,43.65625 V 79.375 l 91.281253,0"
id="path2683"
sodipodi:nodetypes="ccc" />
<text
xml:space="preserve"
style="font-size:4.23333px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
x="58.208332"
y="71.4375"
id="text3874"><tspan
sodipodi:role="line"
id="tspan3872"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.265"
x="58.208332"
y="71.4375">сборка</tspan></text>
<text
xml:space="preserve"
style="font-size:4.23333px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
x="58.208332"
y="76.729164"
id="text3878"><tspan
sodipodi:role="line"
id="tspan3876"
style="stroke-width:0.265"
x="58.208332"
y="76.729164">пауза</tspan></text>
<text
xml:space="preserve"
style="font-size:4.23333px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
x="58.208332"
y="66.145836"
id="text3882"><tspan
sodipodi:role="line"
id="tspan3880"
style="stroke-width:0.265"
x="58.208332"
y="66.145836">пауза</tspan></text>
<text
xml:space="preserve"
style="font-size:4.23333px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
x="58.208332"
y="60.854168"
id="text3886"><tspan
sodipodi:role="line"
id="tspan3884"
style="stroke-width:0.265"
x="58.208332"
y="60.854168">пауза</tspan></text>
<text
xml:space="preserve"
style="font-size:4.23333px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
x="58.208332"
y="55.5625"
id="text3890"><tspan
sodipodi:role="line"
id="tspan3888"
style="stroke-width:0.265"
x="58.208332"
y="55.5625">пауза</tspan></text>
<text
xml:space="preserve"
style="font-size:4.23333px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
x="58.208332"
y="50.270836"
id="text3894"><tspan
sodipodi:role="line"
id="tspan3892"
style="stroke-width:0.265"
x="58.208332"
y="50.270836">пауза</tspan></text>
<text
xml:space="preserve"
style="font-size:4.23333px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
x="117.73959"
y="50.270836"
id="text3894-3"><tspan
sodipodi:role="line"
id="tspan3892-7"
style="stroke-width:0.265"
x="117.73959"
y="50.270836">пауза</tspan></text>
<text
xml:space="preserve"
style="font-size:4.23333px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
x="117.73959"
y="55.5625"
id="text3894-3-5"><tspan
sodipodi:role="line"
id="tspan3892-7-0"
style="stroke-width:0.265"
x="117.73959"
y="55.5625">пауза</tspan></text>
<text
xml:space="preserve"
style="font-size:4.23333px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
x="117.73959"
y="60.854168"
id="text3894-3-2"><tspan
sodipodi:role="line"
id="tspan3892-7-1"
style="stroke-width:0.265"
x="117.73959"
y="60.854168">пауза</tspan></text>
<text
xml:space="preserve"
style="font-size:4.23333px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
x="84.666664"
y="76.729164"
id="text3898"><tspan
sodipodi:role="line"
id="tspan3896"
style="stroke-width:0.265"
x="84.666664"
y="76.729164">исключение</tspan></text>
<text
xml:space="preserve"
style="font-size:4.23333px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
x="111.125"
y="66.145836"
id="text4652"><tspan
sodipodi:role="line"
id="tspan4650"
style="stroke-width:0.265"
x="111.125"
y="66.145836">обработка</tspan></text>
<text
xml:space="preserve"
style="font-size:4.23333px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
x="117.73959"
y="71.4375"
id="text4656"><tspan
sodipodi:role="line"
id="tspan4654"
style="stroke-width:0.265"
x="117.73959"
y="71.4375">сборка</tspan></text>
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="m 44.979166,75.406249 h 11.90625"
id="path6298" />
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="m 47.624999,70.114582 h 9.260417"
id="path6304" />
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="m 46.302083,64.822917 10.583333,-10e-7"
id="path6308"
sodipodi:nodetypes="cc" />
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="m 50.270833,59.531249 h 6.614583"
id="path6310" />
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="m 51.593749,54.239584 h 5.291667"
id="path6312" />
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="M 46.302083,48.947917 H 56.885416"
id="path6314" />
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="m 56.885416,47.625001 v 2.645833"
id="path6316" />
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="m 56.885416,52.916667 v 2.645834"
id="path6318" />
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="m 56.885416,58.208333 v 2.645833"
id="path6320" />
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="m 56.885416,63.499999 v 2.645833"
id="path6322" />
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="m 56.885416,68.791666 v 2.645833"
id="path6324" />
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="m 56.885416,74.083332 v 2.645834"
id="path6326" />
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="m 74.083332,68.791666 v 2.645833"
id="path6328" />
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="m 74.083332,74.083332 v 2.645834"
id="path6330" />
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="M 74.083332,66.145832 V 63.499999"
id="path6332" />
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="M 74.083332,60.854166 V 58.208333"
id="path6334" />
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="M 74.083332,55.562501 V 52.916667"
id="path6336" />
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="M 74.083332,50.270834 V 47.625001"
id="path6338" />
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="m 74.083332,75.406249 h 9.260417"
id="path6340" />
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="m 83.343749,74.083332 v 2.645834"
id="path6342" />
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="m 74.083332,70.114582 42.333338,10e-7"
id="path6344"
sodipodi:nodetypes="cc" />
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="M 116.41667,68.791667 V 71.4375"
id="path6346" />
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="M 74.083332,64.822916 H 109.80208"
id="path6348" />
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="m 109.80208,63.499999 v 2.645833"
id="path6350" />
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="m 133.61458,63.499999 v 2.645833"
id="path6352" />
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="m 133.61458,64.822916 2.64584,10e-7"
id="path6354"
sodipodi:nodetypes="cc" />
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="M 133.61458,68.791667 V 71.4375"
id="path6366" />
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="m 133.61458,70.114583 2.64584,0"
id="path6368"
sodipodi:nodetypes="cc" />
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="m 111.125,74.083332 2.64583,2.645834"
id="path6376" />
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="M 113.77083,74.083332 111.125,76.729166"
id="path6378" />
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="m 74.083332,59.531249 42.333338,10e-7"
id="path6382"
sodipodi:nodetypes="cc" />
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="m 74.083332,54.239584 42.333338,-10e-7"
id="path6384"
sodipodi:nodetypes="cc" />
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="m 74.083332,48.947917 42.333338,0"
id="path6386"
sodipodi:nodetypes="cc" />
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="m 116.41667,47.625 v 2.645833"
id="path6453" />
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="M 116.41667,52.916666 V 55.5625"
id="path6455" />
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="m 116.41667,58.208332 v 2.645833"
id="path6457" />
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="M 133.61459,60.854165 V 58.208332"
id="path6459" />
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="M 133.61459,55.5625 V 52.916666"
id="path6461" />
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="M 133.61459,50.270833 V 47.625"
id="path6463" />
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="m 133.61459,59.531248 2.64583,2e-6"
id="path6465"
sodipodi:nodetypes="cc" />
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="m 133.61459,54.239583 2.64583,0"
id="path6473"
sodipodi:nodetypes="cc" />
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="m 133.61459,48.947916 2.64583,10e-7"
id="path6481"
sodipodi:nodetypes="cc" />
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1;marker-end:url(#TriangleStart)"
d="m 112.44792,75.40625 c 0.21816,-0.711191 0.20876,-1.490311 -0.0265,-2.196036 -0.23524,-0.705725 -0.6952,-1.334657 -1.29644,-1.772714 -0.65756,-0.479088 -1.45305,-0.720365 -2.19238,-1.05993 -0.36966,-0.169783 -0.72982,-0.367001 -1.04363,-0.625852 -0.3138,-0.258851 -0.58082,-0.582696 -0.73274,-0.960051 -0.2081,-0.516891 -0.18358,-1.122462 0.0656,-1.620843 0.24919,-0.498381 0.71894,-0.881333 1.25731,-1.024991"
id="path6489"
inkscape:path-effect="#path-effect6491"
inkscape:original-d="m 112.44792,75.40625 c 0.44124,-0.881679 -1.76363,-3.086542 -1.32292,-3.96875 0.44071,-0.882208 -2.64557,-0.881679 -3.96875,-2.645833 -1.32318,-1.764154 0.44124,-1.763626 1.32292,-2.645834"
sodipodi:nodetypes="cssc" />
<text
xml:space="preserve"
style="font-size:4.23333px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
x="18.520834"
y="44.979168"
id="text8188"><tspan
sodipodi:role="line"
id="tspan8186"
style="stroke-width:0.265;fill:#000000;fill-opacity:1;stroke:none"
x="18.520834"
y="44.979168">...</tspan></text>
<circle
id="path8309"
style="fill:#000000;stroke:none;stroke-width:0.264583"
cx="137.58333"
cy="48.947918"
r="0.39749998" />
<circle
id="path8311"
style="fill:#000000;stroke:none;stroke-width:0.264583"
cx="138.90625"
cy="48.947918"
r="0.39749998" />
<circle
id="path8313"
style="fill:#000000;stroke:none;stroke-width:0.264583"
cx="140.22917"
cy="48.947918"
r="0.39749998" />
<circle
id="path8315"
style="fill:#000000;stroke:none;stroke-width:0.264583"
cx="137.58333"
cy="54.239582"
r="0.39749998" />
<circle
id="path8317"
style="fill:#000000;stroke:none;stroke-width:0.264583"
cx="138.90625"
cy="54.239582"
r="0.39749998" />
<circle
id="path8319"
style="fill:#000000;stroke:none;stroke-width:0.264583"
cx="140.22917"
cy="54.239582"
r="0.39749998" />
<circle
id="path8321"
style="fill:#000000;stroke:none;stroke-width:0.264583"
cx="137.58333"
cy="59.53125"
r="0.39749998" />
<circle
id="path8323"
style="fill:#000000;stroke:none;stroke-width:0.264583"
cx="138.90625"
cy="59.53125"
r="0.39749998" />
<circle
id="path8325"
style="fill:#000000;stroke:none;stroke-width:0.264583"
cx="140.22917"
cy="59.53125"
r="0.39749998" />
<circle
id="path8327"
style="fill:#000000;stroke:none;stroke-width:0.264583"
cx="137.58333"
cy="64.822914"
r="0.39749998" />
<circle
id="path8329"
style="fill:#000000;stroke:none;stroke-width:0.264583"
cx="138.90625"
cy="64.822914"
r="0.39749998" />
<circle
id="path8331"
style="fill:#000000;stroke:none;stroke-width:0.264583"
cx="140.22917"
cy="64.822914"
r="0.39749998" />
<circle
id="path8333"
style="fill:#000000;stroke:none;stroke-width:0.264583"
cx="137.58333"
cy="70.114586"
r="0.39749998" />
<circle
id="path8335"
style="fill:#000000;stroke:none;stroke-width:0.264583"
cx="138.90625"
cy="70.114586"
r="0.39749998" />
<circle
id="path8337"
style="fill:#000000;stroke:none;stroke-width:0.264583"
cx="140.22917"
cy="70.114586"
r="0.39749998" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

View File

@ -6,7 +6,7 @@
\section{Семинар: данные и функции}
\subsection{Инструментарий}
\begin{itemize}
\item Презентация для преподавателя, ведущего семинар;
\item \href{https://docs.google.com/presentation/d/1GBiXN2dfVc0LlDi4AXpnJMcJZnvK4WHZnIY34Sd3EE0/edit}{Презентация} для преподавателя, ведущего семинар;
\item \href{https://drive.google.com/file/d/1LWyE8aEy4-1gsognqhXIXwDcoLviVge4/view}{Фон} GeekBrains для проведения семинара в Zoom;
\item JDK любая 11 версии и выше;
\item \href{https://www.jetbrains.com/idea/download}{IntelliJ IDEA Community Edition} для практики и примеров используется IDEA.
@ -26,29 +26,29 @@
@ Что происходит & @ Время & @ Слайды & @ Описание \\
\hline
\endhead
@ Организационный момент & 5 tag(beg) & @ 1-4 & @ Преподаватель ожидает студентов, поддерживает активность и коммуникацию в чате, озвучиает цели и планы на семинар. Важно упомянуть, что выполнение домашних заданий с лекции является, фактически, подготовкой к семинару \\
@ Организационный момент & 5 tag(beg) & @ 1-5 & @ Преподаватель ожидает студентов, поддерживает активность и коммуникацию в чате, озвучиает цели и планы на семинар. Важно упомянуть, что выполнение домашних заданий с лекции является, фактически, подготовкой к семинару \\
\hline
@ Quiz & 5 & @ 3-14 & @ Преподаватель задаёт вопросы викторины, через 30 секунд демонстрирует слайд-подсказку и ожидает ответов (4 вопроса, по минуте на ответ) \\
@ Quiz & 5 & @ 6-18 & @ Преподаватель задаёт вопросы викторины, через 30 секунд демонстрирует слайд-подсказку и ожидает ответов (4 вопроса, по минуте на ответ) \\
\hline
@ Рассмотрение ДЗ лекции & 10 & @ 15-18 & @ Преподаватель демонстрирует свой вариант решения домашнего задания с лекции, возможно, по предварительному опросу, демонстрирует и разбирает вариант решения одного из студентов \\
@ Рассмотрение ДЗ лекции & 10 & @ 19-23 & @ Преподаватель демонстрирует свой вариант решения домашнего задания с лекции, возможно, по предварительному опросу, демонстрирует и разбирает вариант решения одного из студентов \\
\hline
@ Вопросы и ответы & 10 & @ 19 & @ Преподаватель ожидает вопросов по теме прошедшей лекции, викторины и продемонстрированной работы \\
@ Вопросы и ответы & 10 & @ 24 & @ Преподаватель ожидает вопросов по теме прошедшей лекции, викторины и продемонстрированной работы \\
\hline
@ Задание 1 & 10 & @ 20-22 & @ Сравнить насколько разные могут быть прочтения одного и того же технического задания - одна функция для двух значений, возврат значений, возврат индекса, объявление исходного массива внутри функции поиска и др); \\
@ Задание 1 & 10 & @ 25-28 & @ Сравнить насколько разные могут быть прочтения одного и того же технического задания - одна функция для двух значений, возврат значений, возврат индекса, объявление исходного массива внутри функции поиска и др); \\
\hline
@ Задание 2 & 10 & @ 23-25 & @ Корректная манипуляция индексами, как следствие, сокращение числа возможных проходов по массиву и ускорение работы приложени \\
@ Задание 2 & 10 & @ 29-32 & @ Корректная манипуляция индексами, как следствие, сокращение числа возможных проходов по массиву и ускорение работы приложени \\
\hline
@ Перерыв (если нужен) & 5 & @ 26 & @ Преподаватель предлагает студентам перерыв на 5 минут (студенты голосуют) \\
@ Перерыв (если нужен) & 5 & @ 33 & @ Преподаватель предлагает студентам перерыв на 5 минут (студенты голосуют) \\
\hline
@ Задание 3 & 20 & @ 27-29 & @ Формирование алгоритмического мышления при решении задач с описанием верхнего уровня \\
@ Задание 3 & 20 & @ 34-37 & @ Формирование алгоритмического мышления при решении задач с описанием верхнего уровня \\
\hline
@ Задание 4 & 15 & @ 27-29 & @ Понимание внутренней механики работы фреймворка коллекций, повышение уровня абстракции написанного кода \\
@ Задание 4 & 15 & @ 38-41 & @ Понимание внутренней механики работы фреймворка коллекций, повышение уровня абстракции написанного кода \\
\hline
@ Задание 5 (необязат) & 20 & @ 27-29 & @ Описание базовых алгоритмов манипуляции данными с применением вспомогательных массивов \\
@ Задание 5 (необязат) & 20 & @ 42-44 & @ Описание базовых алгоритмов манипуляции данными с применением вспомогательных массивов \\
\hline
@ Домашнее задание & 5 & @ 39 & @ Объясните домашнее задание, подведите итоги урока \\
@ Домашнее задание & 5 & @ 45-46 & @ Объясните домашнее задание, подведите итоги урока \\
\hline
@ Рефлексия & 10 tag(end) & @ 40-42 & @ Преподаватель запрашивает обратную связь \\
@ Рефлексия & 10 tag(end) & @ 47-48 & @ Преподаватель запрашивает обратную связь \\
\hline
@ Длительность & sum(cell(beg):cell(end)) & & \\
\hline
@ -364,7 +364,7 @@ void pigeon(int[] arr) {
final int min = getMin(arr);
final int max = getMax(arr);
int[] freq = new int[max - min + 1];
for (int i = 0; i < size; i++)
for (int i = 0; i < arr.length; i++)
freq[arr[i] - min]++;
int arrIndex = 0;

View File

@ -59,7 +59,7 @@
\setlength{\headheight}{33pt}
\fancyhf{}
\lhead{\includegraphics[height=5mm]{logo.png}}
% \rhead{И.И. Овчинников \\ \href{https://t.me/ivanigorevichfeed}{Telegram: ivanigorevichfeed}}
\rhead{И.И. Овчинников \\ \href{https://t.me/ivanigorevichfeed}{Telegram: ivanigorevichfeed}}
\chead{\thepage}
\cfoot{\faRocket}
% \rfoot{Всего слов: \wordcount}