This commit is contained in:
Ivan I. Ovchinnikov 2022-12-30 12:21:30 +03:00
commit e3ac8548f5
76 changed files with 5851 additions and 627 deletions

1
.gitignore vendored
View File

@ -4,6 +4,7 @@
/.vscode
/build/*
/svg-inkscape/*
/*/build/*
/sources-draft

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
build/jtc3-03a.pdf Normal file

Binary file not shown.

BIN
build/jtc4-04a.pdf Normal file

Binary file not shown.

View File

@ -23,12 +23,14 @@
\newpage
\subfile{jtc2-02a}
\newpage
\subfile{jtd6-11a}
\subfile{jtc3-03a}
%\newpage
%\subfile{jtd6-11a}
\section{Специализация: ООП}
%\section{Специализация: ООП}
\section{Специализация: Тонкости работы}
Файловая система и представление данных; Пакеты \code{java.io}, \code{java.nio}, \code{String}, \code{StringBuilder}, string pool, ?JSON/XML?
%\section{Специализация: Тонкости работы}
%Файловая система и представление данных; Пакеты \code{java.io}, \code{java.nio}, \code{String}, \code{StringBuilder}, string pool, ?JSON/XML?
\newpage
\appendix

View File

@ -1,327 +0,0 @@
\documentclass[j-spec.tex]{subfiles}
\begin{document}
\pagestyle{plain}
\sloppy
\tableofcontents
\section{Специализация: ООП}
\subsection{В предыдущем разделе}
Будет рассмотрен базовый функционал языка, то есть основная встроенная функциональность, такая как математические операторы, условия, циклы, бинарные операторы. Далее способы хранения и представления данных в Java, и в конце способы манипуляции данными, то есть функции (в терминах языка называющиеся методами).
\subsection{В этом разделе}
Разберём такие основополагающих в Java вещи, как классы и объекты, а также с тем, как применять на практике основные принципы ООП: наследование, полиморфизм и инкапсуляцию. Дополнительно рассмотрим устройство памяти в джава.
\begin{itemize}
\item \nom{Класс}{определяет форму и сущность объекта и является логической конструкцией, на основе которой построен весь язык Java. Определяет новый тип данных};
\item \nom{Объект}{конкретный экземпляр класса, созданный в программе};
\item \nom{Статика}{(статический контекст) - };
\item \nom{Стек}{- };
\item \nom{Куча}{- };
\item \nom{Сборщик мусора}{- };
\item \nom{Конструктор}{- };
\item \nom{Вложенный класс}{- };
\item \nom{Внутренний класс}{- };
\item \nom{Инкапсуляция}{- };
\item \nom{Наследование}{- };
\item \nom{Полиморфизм }{- };
\end{itemize}
\subsection{Классы и объекты, поля и методы, статика}
\subsubsection{Классы}
Что такое класс? С точки зрения ООП, \textbf{класс} определяет форму и сущность объекта и является логической конструкцией, на основе которой построен весь язык Java.
\begin{frm}\info
Наиболее важная особенность класса состоит в том, что он определяет новый тип данных, которым можно воспользоваться для создания объектов этого типа
\end{frm}
То есть класс — это шаблон (чертёж), по которому создаются объекты (экземпляры класса). Для определения формы и сущности класса указываются данные, которые он должен содержать, а также код, воздействующий на эти данные. Создаем мы свои классы, когда у нас не хватает уже созданных.
Например, если мы хотим работать в нашем приложении с документами, то необходимо для начала объяснить приложению, что такое документ, описать его в виде класса (чертежа) \code{Document}. Указать, какие у него должны быть свойства: название, содержание, количество страниц, информация о том, кем он подписан и т.п. В этом же классе мы обычно описываем, что можно делать с документами: печатать в консоль, подписывать, изменять содержание, название и т.д. Результатом такого описания и будет класс \code{Document}. Однако, это по-прежнему всего лишь чертеж хранимых данных (состояний) и способы взаимодействия с этими данными.
Если нам нужны конкретные документы, а нам они обязательно нужны, то необходимо создавать \textbf{объекты}: документ №1, документ №2, документ №3. Все эти документы будут иметь одну и ту же структуру (описанные нами название, содержание, ...), с ними можно выполнять одни и те же описанные нами действия (печатать, подписать, ...), но наполнение будет разным, например, в первом документе содержится приказ о назначении работника на должность, во втором, о выдаче премии отделу разработки и т.д.
Начнём с малого, напишем свой первый класс. Представим, что необходимо работать в приложении с котами. Java ничего не знает о том, что такое коты, поэтому необходимо создать новый класс (тип данных), и объяснить что такое кот. Создадим новый файл, для простоты в том же пакете, что и главный класс программы.
\begin{figure}[H]
\begin{forest}
for tree={
font=\ttfamily, grow'=0, child anchor=west,
parent anchor=south, anchor=west, calign=first,
edge path={
\noexpand\path [draw, \forestoption{edge}]
(!u.south west) +(7.5pt,0) |- node[fill,inner sep=1.5pt]
{} (.child anchor)\forestoption{edge label};
}, before typesetting nodes={
if n=1 {insert before={[,phantom]}} {} },
fit=band, before computing xy={l=20pt},
}
[Sample
[src
[ru
[gb
[jcore
[sample
[Main.java]
[Cat.java]
]
]
]
]
]
[out
]
[README.md]
]
\end{forest}
\caption{Структура проекта}
\label{pic:simple-tree}
\end{figure}
\subsubsection{Поля класса}
Начнем описывать в классе \code{Cat} так называемый API кота. Как изестно, имя класса должно совпадать с именем файла, в котором он объявлен, т.е. класс \code{Cat} должен находиться в файле \code{Cat.java}. Пусть у котов есть три свойства: \code{name} (кличка), \code{color} (цвет) и \code{age} (возраст); совокупность этих свойств называется состоянием, и коты пока ничего не умеют делать. Класс \code{Cat} будет иметь вид, представленный в листинге \hrf{lst:class-simple}. Свойства класса, записанные таким образом, в виде переменных, называются \textbf{полями}.
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Структура кота в программе},label={lst:class-simple}]
package ru.gb.jcore;
public class Cat {
String name;
String color;
int age;
}
\end{lstlisting}
\begin{frm} \excl
Для новичка важно не запутаться, класс кота мы описали в отдельном файле, а создавать объекты и совершать манипуляции следует в основном классе программы, не может же кот назначить имя сам себе.
\end{frm}
Мы рассказали программе, что такое коты, теперь если мы хотим создать в нашем приложении конкретного кота, следует воспользоваться оператором \code{new Cat();} в основном классе программы. Более подробно разберём, что происходит в этой строке, чуть позже, пока же нам достаточно знать, что мы создали объект типа \code{Cat} (экземпляр класса \code{Cat}), и запомнить эту конструкцию. Для того чтобы с ним (экземпляром) работать, можем положить его в переменную, которой дать идентификатор \code{cat1}.
\begin{lstlisting}[language=Java,style=JCodeStyle]
Сat cat0;
cat0 = new Cat();
Cat cat1 = new Cat();
\end{lstlisting}
В листинге выше можно увидеть все три операции (объявление, присваивание и инициализацию) и становится понятно, как можно создавать объекты. Также известно, что в переменной не лежит сам объект, а только ссылка на него. Объект \code{cat1} создан по чертежу \code{Cat}, это значит, что у него есть поля \code{name}, \code{color}, \code{age}, с которыми можно работать: получать или изменять их значения.
\begin{frm} \info
Для доступа к полям объекта используется оператор точка, который связывает имя объекта с именем поля. Например, чтобы присвоить полю \code{color} объекта \code{cat1} значение «Белый», нужно выполнить код \code{cat1.color = "Белый"};
\end{frm}
Операция «точка» служит для доступа к полям и методам объекта по его имени. Мы уже использовали оператор «точка» для доступа к полю с длиной массива, например. Рассмотрим пример консольного приложения, работающего с объектами класса \code{Cat}. Создадим двух котов, один будет белым Барсиком 4х лет, второй чёрным Мурзиком шести лет, и просто выведем информацию о них в терминал.
\begin{lstlisting}[language=Java,style=JCodeStyle]
package ru.gb.jcore;
public class Main{
public static void main(String[] args) {
Cat cat1 = new Cat();
Cat cat2 = new Cat();
cat1.name = "Barsik";
cat1.color = "White";
cat1.age = 4;
cat2.name = "Murzik";
cat2.color = "Black";
cat2.age = 6;
System.out.println("Cat1 named: " + cat1.name +
" is " + cat1.color +
" has age: " + cat1.age);
System.out.println("Cat2 named: " + cat2.name +
" is " + cat2.color +
" has age: " + cat2.age);
}
}
\end{lstlisting}
в результате работы программы в консоли появятся следующие строки:
\begin{verbatim}
Cat1 named: Barsik is White has age: 4
Cat2 named: Murzik is Black has age: 6
\end{verbatim}
Вначале мы создали два объекта типа \code{Cat}: \code{cat1} и \code{cat2}, соответственно, они имеют одинаковый набор полей \code{name}, \code{color}, \code{age}. Почему? Потому что они принадлежат одному классу, созданы по одному шаблону. Объекты всегда «знают», какого они класса. Однако каждому из них в эти поля записаны разные значения. Как видно из результата печати в консоли, изменение значения полей одного объекта, никак не влияет на значения полей другого объекта. Данные объектов \code{cat1} и \code{cat2} изолированы друг от друга. А значит мы делаем вывод о том, поля хранятся в классе, а значения полей хранятся в объектах. Логическая структура, демонстрирующая отношения объектов и классов, в том числе в части хранения полей и их значений показана на рис. \hrf{pic:class-obj-fields}.
\begin{figure}[H]
\centering
\def\svgscale{0.42}
\fontsize{6}{1}\selectfont
\input{pics/jc-03-class-obj-fields.svg}
\caption{Логическая структура отношения класс-объект}
\label{pic:class-obj-fields}
\end{figure}
\subsubsection{Объекты}
Разобравшись с тем, как создавать новые типы данных (классы) и мельком посмотрев, как создаются объекты, нужно подробнее разобрать, как создавать объекты, и что при этом происходит. Создание объекта как любого ссылочного типа данных проходит в два этапа. Как и в случае с уже известными нам массивами.
\begin{itemize}
\item Сначала создается переменная, имеющая интересующий нас тип, в неё возможно записать ссылку на объект;
\item затем необходимо выделить память под объект;
\item создать и положить объект в выделенную часть памяти;
\item и сохранить ссылку на этот объект в памяти - в нашу переменную.
\end{itemize}
Для непосредственного создания объекта применяется оператор \code{new}, который динамически резервирует память под объект и возвращает ссылку на него, в общих чертах эта ссылка представляет собой адрес объекта в памяти, зарезервированной оператором \code{new}.
\begin{lstlisting}[language=Java,style=JCodeStyle]
Сat cat1; // cat1 = null;
cat1 = new Cat();
Cat cat2 = new Cat();
\end{lstlisting}
В первой строке кода переменная \code{cat1} объявляется как ссылка на объект типа \code{Cat} и пока ещё не ссылается на конкретный объект (первоначально значение переменной \code{cat1} равно \code{null}). В следующей строке выделяется память для объекта типа \code{Cat}, и в переменную \code{cat1} сохраняется ссылка на него. После выполнения второй строки кода переменную \code{cat1} можно использовать так, как если бы она была объектом типа \code{Cat}. Обычно новый объект создается в одну строку, то есть инициализируется.
\subsubsection{Оператор \code{new}}
\begin{frm}\info
[квалификаторы] ИмяКласса имяПеременной = \textbf{\code{new}} ИмяКласса();
\end{frm}
Оператор \code{new} динамически выделяет память для нового объекта, общая форма применения этого оператора имеет вид как на врезке выше, но на самом деле справа - не имя класса, конструкция ИмяКласса() в правой части выполняет вызов конструктора данного класса, который подготавливает вновь создаваемый объект к работе.
Именно от количества применений оператора \code{new} будет зависеть, сколько именно объектов будет создано в программе.
\begin{lstlisting}[language=Java,style=JCodeStyle]
Cat cat1 = new Cat();
Cat cat2 = cat1;
cat1.name = "Barsik";
cat1.color = "White";
cat1.age = 4;
cat2.name = "Murzik";
cat2.color = "Black";
cat2.age = 6;
System.out.println("Cat1 named: " + cat1.name +
" is " + cat1.color +
" has age: " + cat1.age);
System.out.println("Cat2 named: " + cat2.name +
" is " + cat2.color +
" has age: " + cat2.age);
\end{lstlisting}
На первый взгляд может показаться, что переменной \code{cat2} присваивается ссылка на копию объекта \code{cat1}, т.е. переменные \code{cat1} и \code{cat2} будут ссылаться на разные объекты в памяти. Но это не так. На самом деле \code{cat1} и \code{cat2} будут ссылаться на один и тот же объект. Присваивание переменной \code{cat1} значения переменной \code{cat2} не привело к выделению области памяти или копированию объекта, лишь к тому, что переменная \code{cat2} содержит ссылку на тот же объект, что и переменная \code{cat1}. Это явление дополнительно подчёркивает ссылочную природу данных в языке Java.
Таким образом, любые изменения, внесённые в объект по ссылке \code{cat2}, окажут влияние на объект, на который ссылается переменная \code{cat1}, поскольку \textit{это один и тот же объект в памяти}. Поэтому результатом выполнения кода, где мы как будто бы указали возраст второго кота, равный шести годам, станут строки, показывающие, что по обеим ссылкам оказался кот возраста шесть лет с именем Мурзика.
\begin{frm}\info
Множественные ссылки на один и тот же объект в памяти довольно легко себе представить как ярлыки для запуска одной и той же программы на рабочем столе и в меню быстрого запуска. Или если на один и тот же шкафчик в раздевалке наклеить два номера - сам шкафчик можно будет найти по двум ссылкам на него.
\end{frm}
\subsubsection{Методы}
Ранее было сказано о том, что в языке Java любая программа состоит из классов и функций, которые могут описываться только внутри них. Именно поэтому все функции в языке Java являются методами. А метод - это функция, являющаяся частью некоторого класса, которая может выполнять операции над данными этого класса.
\begin{frm} \info
Метод - это функция, принадлежащая классу
\end{frm}
Метод для своей работы может использовать поля объекта и/или класса, в котором определен, напрямую, без необходимости передавать их во входных параметрах. Это похоже на использование глобальных переменных в функциях, но в отличие от глобальных переменных, метод может получать прямой доступ только к членам класса. Самые простые методы работают с данными объектов. Методы чаще всего формируют API классов, то есть способ взаимодействия с классами, интерфейс. Место методов во взаимодействии классов и объектов показано на рис. \hrf{pic:class-obj-nostatic}.
\begin{figure}[H]
\centering
\def\svgscale{0.42}
\fontsize{6}{1}\selectfont
\input{pics/jc-03-class-obj-nostatic.svg}
\caption{Логическая структура отношения класс-объект}
\label{pic:class-obj-nostatic}
\end{figure}
Лайвкод 03-метод & Вернёмся к примеру с котиками. Все мы знаем, что котики умеют урчать, мяукать и смешно прыгать. В целях демонстрации мы в описании этих действий просто будем делать разные выводы в консоль, хотя мы и можем научить нашего котика выбирать минимальное значение из массива, но это было бы неожиданно. Итак опишем метод например подать голос и прыгать. \\ \hline
Лайвкод 03-метод-вызов & Обращение к методам выглядит очень похожим на стандартный способом, через точку, как к полям. Теперь когда мы хотим позвать нашего котика, он нам скажет, мяу, я имя котика, а если мы решили что котику надо прыгать, он решит, прилично-ли это - прыгать в его возрасте. Как видно, барсик замечательно прыгает, а мурзик от прыжков воздержался, хотя попрыгать мы попросили их обоих \\ \hline
\subsubsection{Задание для самопроверки}
\begin{enumerate}
\item Что такое класс?
\item Что такое поле класса?
\item На какие три этапа делится создание объекта?
\end{enumerate}
\subsection{Стек и куча}
\subsection{Сборка мусора}
\subsection{Конструкторы}
\subsection{Инкапсуляция}
\subsection{Наследование}
\subsection{Полиморфизм}
\begin{verbatim}
Cat1 named: Murzik is Black has age: 6
Cat2 named: Murzik is Black has age: 6
\end{verbatim}
\begin{lstlisting}[language=Java,style=JCodeStyle]
public class Cat {
String name;
String color;
int age;
void voice() {
System.out.println(name + " meows");
}
void jump() {
if (this.age < 5) System.out.println(name + " jumps");
}
}
\end{lstlisting}
- Также, хотелось бы отметить, что мы можем использовать -Xms и -Xmx опции JVM, чтобы определить начальный и максимальный размер памяти в куче. Для стека определить размер памяти можно с помощью опции -Xss;
\begin{lstlisting}[language=Java,style=JCodeStyle]
public class Cat {
private String name;
private String color;
private int age;
public Cat() {
System.out.println("constructor is constructing...");
name = "Barsik";
color = "White";
age = 2;
}
}
\end{lstlisting}
\begin{lstlisting}[language=Java,style=JCodeStyle]
public class Cat {
private String name;
private String color;
private int age;
Cat(String n, String c, int a) {
System.out.println("constructor is constructing...");
name = n;
color = c;
age = a;
}
}
\end{lstlisting}
\begin{lstlisting}[language=Java,style=JCodeStyle]
Cat cat1 = new Cat("Barsik", "White", 4);
Cat cat2 = new Cat("Murzik", "Black", 6);
\end{lstlisting}
\begin{lstlisting}[language=C,style=CCodeStyle]
public class Cat {
private String name;
private String color;
private int age;
public Cat(String name, String color, int age) {
this.name = name;
this.color = color;
this.age = age;
}
}
\end{lstlisting}
ключевое слово this в Java используется только в составе экземпляра класса. Но неявно ключевое слово this передается во все методы, кроме статических (поэтому this часто называют неявным параметром) и может быть использовано для обращения к объекту, вызвавшему метод.
\newpage
\printnomenclature[40mm]
\end{document}

View File

@ -1,72 +0,0 @@
% enum Color{
% RED("#FF0000"), BLUE("#0000FF"), GREEN("#00FF00");
% private String code;
% Color(String code){
% this.code = code;
% }
% public String getCode(){ return code;}
% }
%public class Main{
% public static void main(String[] args) {
% System.out.println(Color.RED.getCode());
% System.out.println(Color.GREEN.getCode());
% }
%}
% package ru.gb.jcore;
% public class Orange {
% public void squeezeJuice(){
% System.out.println("Squeeze juice ...");
% }
% class Juice{
% public void flow(){
% System.out.println("Juice dripped ...");
% }
% }
% }
% package ru.gb.jcore;
% public class Main {
% public static void main(String[] args) {
% Orange orange = new Orange();
% Orange.Juice juice = orange.new Juice();
% orange.squeezeJuice();
% juice.flow();
% }
% }
%///////////////////////////////
% public class Orange {
% private Juice juice;
% public Orange(){
% this.juice = new Juice();
% }
% public void squeezeJuice(){
% System.out.println("Squeeze juice ...");
% juice.flow();
% }
% private class Juice{
% public void flow(){
% System.out.println("Juice dripped ...");
% }
% }
% }
% public class Main {
% public static void main(String[] args) {
% Orange orange = new Orange();
% orange.squeezeJuice();
% }
% }

View File

@ -2,7 +2,6 @@
\begin{document}
\pagestyle{plain}
\sloppy
\tableofcontents
\section{Платформа: история и окружение}
\subsection{В этом разделе}
@ -14,14 +13,14 @@
\item \nom{JRE}{(от англ. Java Runtime Environment) — минимальная (без компилятора и других средств разработки) реализация виртуальной машины, необходимая для исполнения Java-приложений. Состоит из виртуальной машины Java Virtual Machine и библиотеки Java-классов.}
\item \nom{JVM}{(от англ. Java Virtual Machine) — виртуальная машина Java, основная часть исполняющей системы Java. Виртуальная машина Java исполняет байт-код, предварительно созданный из исходного текста Java-программы компилятором. JVM может также использоваться для выполнения программ, написанных на других языках программирования.}
\item \nom{JIT}{(англ. Just-in-Time, компиляция «точно в нужное время»), динамическая компиляция — технология увеличения производительности программных систем, использующих байт-код, путём компиляции байт-кода в машинный код или в другой формат непосредственно во время работы программы. Таким образом достигается высокая скорость выполнения по сравнению с интерпретируемым байт-кодом за счёт увеличения потребления памяти (для хранения результатов компиляции) и затрат времени на компиляцию. Технология JIT базируется на двух более ранних идеях, касающихся среды выполнения: компиляции байт-кода и динамической компиляции.}
\item \nom{CLI}{(англ. Command Line Interface, Интерфейс командной строки) — разновидность текстового интерфейса между человеком и компьютером, в котором инструкции компьютеру даются в основном путём ввода с клавиатуры текстовых строк (команд). Также известен под названиями «консоль» и «терминал».}
\item \nom{CLI}{(англ. Command line interface, Интерфейс командной строки) — разновидность текстового интерфейса между человеком и компьютером, в котором инструкции компьютеру даются в основном путём ввода с клавиатуры текстовых строк (команд). Также известен под названиями «консоль» и «терминал».}
\item \nom{Docker}{программное обеспечение для автоматизации развёртывания и управления приложениями, контейнеризатор приложений. Позволяет «упаковать» приложение со всем его окружением и зависимостями в контейнер, который может быть развёрнут почти на любой системе.}
\end{itemize}
\nomenclature{GPL}{GNU General Public License (чаще всего переводят как Открытое лицензионное соглашение GNU) — лицензия на свободное программное обеспечение, созданная в рамках проекта GNU, по которой автор передаёт программное обеспечение в общественную собственность. Её также сокращённо называют GNU GPL или даже просто GPL, если из контекста понятно, что речь идёт именно о данной лицензии. GNU Lesser General Public License (LGPL) — это ослабленная версия GPL, предназначенная для некоторых библиотек ПО.}
\subsection{Краткая история (причины возникновения)}
\begin{itemize}
\item Язык создавали для разработки встраиваемых систем, сетевых приложений и прикладного \nom{ПО}{(программное обеспечение) -- программа или множество программ, используемых для управления компьютером.};
\item Язык создавали для разработки встраиваемых систем, сетевых приложений и прикладного \nom{ПО}{программное обеспечение};
\item Популярен из-за скорости исполнения и полного абстрагирования от исполнителя кода;
\item Часто используется для программирования бэк-энда веб-приложений из-за изначальной нацеленности на сетевые приложения.
\end{itemize}
@ -44,10 +43,10 @@
\subsection{Базовый инструментарий, который понадобится (выбор IDE)}
\begin{itemize}
\item NetBeans -- хороший, добротный инструмент с лёгким ностальгическим оттенком;
\item Eclipse -- для поклонников Eclipse Foundation и швейцарских ножей с полусотней лезвий;
\item IntelliJ IDEA -- стандарт де-факто, используется на курсе и в большинстве современных компаний;
\item Android Studio -- если заниматься мобильной разработкой.
\item NetBeans - хороший, добротный инструмент с лёгким ностальгическим оттенком;
\item Eclipse - для поклонников Eclipse Foundation и швейцарских ножей с полусотней лезвий;
\item IntelliJ IDEA - стандарт де-факто, используется на курсе и в большинстве современных компаний;
\item Android Studio - если заниматься мобильной разработкой.
\end{itemize}
\subsubsection{Задания для самопроверки}
@ -66,7 +65,7 @@
В последнее время, с развитием контейнеризации приложений, часто устанавливают инструментарий в Docker-контейнер и ведут разработку прямо в контейнере, это позволяет не захламлять компьютер разработчика разными версиями инструментария и быстро разворачивать свои приложения в \nom{CI}{(англ. Continious Integration) практика разработки программного обеспечения, которая заключается в постоянном слиянии рабочих копий в общую основную ветвь разработки и выполнении частых автоматизированных сборок проекта для скорейшего выявления потенциальных дефектов и решения интеграционных проблем.} или на целевом сервере.
\begin{frm}
\info В общем случае, для разработки на любом языке программирования нужны так называемые \nom{SDK}{(от англ. software development kit, комплект для разработки программного обеспечения) — это набор инструментов для разработки программного обеспечения в одном устанавливаемом пакете. Они облегчают создание приложений, имея компилятор, отладчик и иногда программную среду. В основном они зависят от комбинации аппаратной платформы компьютера и операционной системы.} (Software Development Kit, англ. -- инструментарий разработчика приложений или инструментарий для разработки приложений). Частный случай такого SDK -- инструментарий разработчика на языке Java -- Java Development Kit.
\info В общем случае, для разработки на любом языке программирования нужны так называемые \nom{SDK}{(от англ. software development kit, комплект для разработки программного обеспечения) — это набор инструментов для разработки программного обеспечения в одном устанавливаемом пакете. Они облегчают создание приложений, имея компилятор, отладчик и иногда программную среду. В основном они зависят от комбинации аппаратной платформы компьютера и операционной системы.} (Software Development Kit, англ. - инструментарий разработчика приложений или инструментарий для разработки приложений). Частный случай такого SDK - инструментарий разработчика на языке Java - Java Development Kit.
\end{frm}
На курсе будет использоваться BellSoft Liberica JDK 11, но возможно использовать и других производителей, например, самую распространённую Oracle JDK. Производителя следует выбирать из требований по лицензированию, так, например, Oracle JDK можно использовать бесплатно только в личных целях, за коммерческую разработку с использованием этого инструментария придётся заплатить.
@ -104,7 +103,7 @@ TL;DR:
Как именно всё работает? Если коротко, то слой за слоем накладывая абстракции. Программы на любом языке программирования исполняются на компьютере, то есть, так или иначе, задействуют процессор, оперативную память и прочие аппаратурные компоненты. Эти аппаратурные компоненты предоставляют для доступа к себе низкоуровневые интерфейсы, которые задействует операционная система, предоставляя в свою очередь интерфейс чуть проще программам, взаимодействующим с ней. Этот интерфейс взаимодействия с \nom{ОС}{(операционная система) — комплекс управляющих и обрабатывающих программ, которые, с одной стороны, выступают как интерфейс между устройствами вычислительной системы и прикладными программами, а с другой стороны — предназначены для управления устройствами, управления вычислительными процессами, эффективного распределения вычислительных ресурсов между вычислительными процессами и организации надёжных вычислений.} мы для простоты будем называть Native API.
С ОС взаимодействует JVM (\href{https://ru.m.wikipedia.org/wiki/Список_виртуальных_машин_Java}{Wikipedia: Список виртуальных машин Java}), то есть, используя Native API, нам становится всё равно, какая именно ОС установлена на компьютере, главное уметь выполняться на JVM. Это открывает простор для создания целой группы языков, они носят общее бытовое название JVM-языки, к ним относят Scala, Groovy, Kotlin и другие. Внутри JVM осуществляется управление памятью, существует механизм исполнения программ, специальный JIT\footnote{JIT, just-in-time -- англ. в\'{о}время, прямо сейчас}-компилятор, генерирующий платформенно-зависимый код.
С ОС взаимодействует JVM (\href{https://ru.m.wikipedia.org/wiki/Список_виртуальных_машин_Java}{Wikipedia: Список виртуальных машин Java}), то есть, используя Native API, нам становится всё равно, какая именно ОС установлена на компьютере, главное уметь выполняться на JVM. Это открывает простор для создания целой группы языков, они носят общее бытовое название JVM-языки, к ним относят Scala, Groovy, Kotlin и другие. Внутри JVM осуществляется управление памятью, существует механизм исполнения программ, специальный JIT\footnote{JIT, just-in-time - англ. в\'{о}время, прямо сейчас}-компилятор, генерирующий платформенно-зависимый код.
JVM для своей работы запрашивает у ОС некоторый сегмент оперативной памяти, в котором хранит данные программы. Это хранение происходит «слоями»:
\begin{enumerate}
@ -112,20 +111,19 @@ JVM для своей работы запрашивает у ОС некотор
\item Survivor Space (heap) сюда перемещаются объекты из предыдущей области после того, как они пережили хотя бы одну сборку мусора. Время от времени долгоживущие объекты из этой области перемещаются в Tenured Space.
\item Tenured (Old) Generation (heap) — Здесь скапливаются долгоживущие объекты (крупные высокоуровневые объекты, синглтоны, менеджеры ресурсов и прочие). Когда заполняется эта область, выполняется полная сборка мусора (full, major collection), которая обрабатывает все созданные JVM объекты.
\item Permanent Generation (non-heap) Здесь хранится метаинформация, используемая JVM (используемые классы, методы и т.п.).
\item Code Cache (non-heap) — эта область используется JVM, когда включена JIT-компиляция, в ней кэшируется скомпилированный платформенно-зависимый код.
\item Code Cache (non-heap) — эта область используется JVM, когда включена JIT-компиляция, в ней кешируется скомпилированный платформенно-зависимый код.
\end{enumerate}
JVM самостоятельно осуществляет сборку так называемого мусора, что значительно облегчает работу программиста по отслеживанию утечек памяти, но важно помнить, что в Java утечки памяти всё равно существуют, особенно при программировании многопоточных приложений.
\begin{figure}[H]
\centering
\def\svgwidth{150mm}
\includesvg{pics/jc-01-jvm-struct.svg}
\caption{Принцип работы JVM}
\includesvg[scale=.9]{pics/jc-01-jvm-struct.svg}
\label{jvm:structure}
\caption{Принцип работы JVM}
\end{figure}
На пользовательском уровне важно не только исполнять базовые инструкции программы, но чтобы эти базовые инструкции умели как-то взаимодействовать со внешним миром, в том числе другими программами, поэтому JVM интегрирована в JRE -- Java Runtime Environment. JRE -- это набор из классов и интерфейсов, реализующих
На пользовательском уровне важно не только исполнять базовые инструкции программы, но чтобы эти базовые инструкции умели как-то взаимодействовать со внешним миром, в том числе другими программами, поэтому JVM интегрирована в JRE - Java Runtime Environment. JRE - это набор из классов и интерфейсов, реализующих
\begin{itemize}
\item возможности сетевого взаимодействия;
\item рисование графики и графический пользовательский интерфейс;
@ -136,7 +134,7 @@ JVM самостоятельно осуществляет сборку так н
\item ... многое другое.
\end{itemize}
Java Development Kit является изрядно дополненным специальными Java приложениями SDK. JDK дополняет JRE не только утилитами для компиляции, но и утилитами для создания документации, отладки, развёртывания приложений и многими другими. В таблице \hrf{table:jdk-contents} на странице \pageref{table:jdk-contents}, приведена примерная структура и состав JDK и JRE, а также указаны их основные и наиболее часто используемые компоненты из состава Java Standard Edition. Помимо стандартной редакции существует и Enterprise Edition, содержащий компоненты для создания веб-приложений, но JEE активно вытесняется фреймворками Spring и Spring Boot.
Java Development Kit является изрядно дополненным специальными Java приложениями SDK. JDK дополняет JRE не только утилитами для компиляции, но и утилитами для создания документации, отладки, развёртывания приложений и многими другими. В таблице \ref{table:jdk-contents} на странице \pageref{table:jdk-contents}, приведена примерная структура и состав JDK и JRE, а также указаны их основные и наиболее часто используемые компоненты из состава Java Standard Edition. Помимо стандартной редакции существует и Enterprise Edition, содержащий компоненты для создания веб-приложений, но JEE активно вытесняется фреймворками Spring и Spring Boot.
\begin{table}[H]
\centering
@ -160,13 +158,13 @@ Java Development Kit является изрядно дополненным сп
& \multicolumn{1}{l|}{} & & \multicolumn{1}{l|}{JVM} & \multicolumn{7}{l|}{Java Hot Spot VM (JIT)} \\ \hline
\end{tabular}
\end{adjustbox}
\caption{Общее представление состава JDK}
\label{table:jdk-contents}
\caption{Общее представление состава JDK}
\end{table}
\subsubsection{Задания для самопроверки}
\begin{enumerate}
\item JVM и JRE -- это одно и тоже?
\item JVM и JRE - это одно и тоже?
\item Что входит в состав JDK, но не входят в состав JRE?
\item Утечки памяти
\begin{itemize}
@ -201,13 +199,13 @@ public class Main {
\textbf{Обычный проект} состоит из пакетов, которые содержат классы, которые в свою очередь как-то связаны между собой и содержат код, который исполняется.
\begin{itemize}
\item Пакеты. Пакеты объединяют классы по смыслу. Классы, находящиеся в одном пакете доступны друг другу даже если находятся в разных проектах. У пакетов есть правила именования: обычно это обратное доменное имя (например, для gb.ru это будет ru.gb), название проекта, и далее уже внутренняя структура. Пакеты именуют строчными латинскими буквами. Чтобы явно отнести класс к пакету, нужно прописать в классе название пакета после оператора \code{package}.
\item Классы. Основная единица исходного кода программы. Одному файлу следует сопоставлять один класс. Название класса -- это имя существительное в именительном падеже, написанное с заглавной буквы. Если требуется назвать класс в несколько слов, применяют UpperCamelCase.
\item Классы. Основная единица исходного кода программы. Одному файлу следует сопоставлять один класс. Название класса - это имя существительное в именительном падеже, написанное с заглавной буквы. Если требуется назвать класс в несколько слов, применяют UpperCamelCase.
\item \code{public static void main(String[] args)}. Метод, который является точкой входа в программу. Должен находиться в публичном классе. При создании этого метода важно полностью повторить его сигнатуру и обязательно написать его с название со строчной буквы.
\item Комментарии. Это часть кода, которую игнорирует компилятор при преобразовании исходного кода. Комментарии бывают:
\begin{itemize}
\item \code{// comment} -- до конца строки. Самый простой и самый часто используемый комментарий.
\item \code{/* comment */} -- внутристрочный или многострочный. Никогда не используйте его внутри строк, несмотря на то, что это возможно.
\item \code{/** comment */} -- комментарий-документация. Многострочный. Из него утилитой Javadoc создаётся веб-страница с комментарием.
\item \code{// comment} - до конца строки. Самый простой и самый часто используемый комментарий.
\item \code{/* comment */} - внутристрочный или многострочный. Никогда не используйте его внутри строк, несмотря на то, что это возможно.
\item \code{/** comment */} - комментарий-документация. Многострочный. Из него утилитой Javadoc создаётся веб-страница с комментарием.
\end{itemize}
\end{itemize}
@ -246,8 +244,8 @@ public class Main {
[README.md]
]
\end{forest}
\caption{Структура простого проекта}
\label{pic:simple-tree}
\caption{Структура простого проекта}
\end{figure}
Содержимое файлов исходного кода представлено ниже.
@ -309,7 +307,7 @@ Hello, world!
\end{lstlisting}
\begin{frm}
\info Скомпилированные классы всегда содержат одинаковые первые четыре байта, которые в шестнадцатеричном представлении формируют надпись «кофе, крошка».
\info Скомпилированные классы всегда содержат одинаковые первые четыре байта, которые в шестнадцатиричном представлении формируют надпись «кофе, крошка».
\begin{figure}[H]
\centering
\includegraphics[width=14cm]{jc-01-cafe-babe.png}
@ -356,7 +354,7 @@ Here is your number: 4.
\centering
\includegraphics[width=12cm]{jc-01-javadoc.png}
\caption{Часть cтраницы автосгенерированной документации}
\label{pic:}
\label{pic:autodoc}
\end{figure}
Чтобы просто создать документацию надо вызвать утилиту javadoc с набором ключей.
@ -368,7 +366,7 @@ Here is your number: 4.
\item \code{-subpackages} нужно ли заглядывать в пакеты-с-пакетами;
\end{itemize}
Часто необходимо указать, в какой кодировке записан файл исходных кодов, и в какой кодировке должна быть выполнена документация (например, файлы исходников на языке Java всегда сохраняются в кодировке \nom{UTF-8}{(от англ. Unicode Transformation Format, 8-bit — «формат преобразования Юникода, 8-бит») — распространённый стандарт кодирования символов, позволяющий более компактно хранить и передавать символы Юникода, используя переменное количество байт (от 1 до 4), и обеспечивающий полную обратную совместимость с 7-битной кодировкой ASCII. Кодировка UTF-8 сейчас является доминирующей в веб-пространстве. Она также нашла широкое применение в UNIX-подобных операционных системах.}, а основная кодировка для ОС Windows -- \nom{cp1251}{набор символов и кодировка, являющаяся стандартной 8-битной кодировкой для русских версий Microsoft Windows до 10-й версии. Была создана на базе кодировок, использовавшихся в ранних русификаторах Windows.})
Часто необходимо указать, в какой кодировке записан файл исходных кодов, и в какой кодировке должна быть выполнена документация (например, файлы исходников на языке Java всегда сохраняются в кодировке \nom{UTF-8}{(от англ. Unicode Transformation Format, 8-bit — «формат преобразования Юникода, 8-бит») — распространённый стандарт кодирования символов, позволяющий более компактно хранить и передавать символы Юникода, используя переменное количество байт (от 1 до 4), и обеспечивающий полную обратную совместимость с 7-битной кодировкой ASCII. Кодировка UTF-8 сейчас является доминирующей в веб-пространстве. Она также нашла широкое применение в UNIX-подобных операционных системах.}, а основная кодировка для ОС Windows - \nom{cp1251}{набор символов и кодировка, являющаяся стандартной 8-битной кодировкой для русских версий Microsoft Windows до 10-й версии. Была создана на базе кодировок, использовавшихся в ранних русификаторах Windows.})
\begin{itemize}
\item \code{-locale ru_RU} язык документации (для правильной расстановки переносов и разделяющих знаков);
\item \code{-encoding} кодировка исходных текстов программы;
@ -446,12 +444,12 @@ Docker также не привносит ничего технологичес
RUN mkdir ./out
\end{lstlisting}
Последнее, что будет сделано при создании образа -- запущена компиляция.
Последнее, что будет сделано при создании образа - запущена компиляция.
\begin{lstlisting}[style=ASMStyle]
RUN javac -sourcepath ./src -d out ./src/ru/gb/dj/Main.java
\end{lstlisting}
Последняя команда в \code{Dockerfile} говорит, что нужно сделать, когда контейнер создаётся из образа и запускается.
Последняя команда в \code{Dockerfile} говорит, что нужно сделать, когда контейнер создаётся из образа и заускается.
\begin{lstlisting}[style=ASMStyle]
CMD java -classpath ./out ru.gb.dj.Main
\end{lstlisting}
@ -460,15 +458,14 @@ Docker-образ и, как следствие, Docker-контейнеры в
Часто команды разработчиков эмулируют таким образом реальный продакшн сервер, используя в качестве исходного образа не JDK, а образ целевой ОС, вручную устанавливают на ней JDK, запуская далее своё приложение.
\subsection*{Практическое задание}
\subsection*{Домашнее задание}
\begin{itemize}
\item Создать проект из трёх классов (основной с точкой входа и два класса в другом пакете), которые вместе должны составлять одну программу, позволяющую производить четыре основных математических действия и осуществлять форматированный вывод результатов пользователю;
\item Скомпилировать проект, а также создать для этого проекта стандартную веб-страницу с документацией ко всем пакетам;
\item Создать Makefile с задачами сборки, очистки и создания документации на весь проект.
\item *Создать два Docker-образа. Один должен компилировать Java-проект обратно в папку на компьютере пользователя, а второй забирать скомпилированные классы и исполнять их.
\item *Создать два Docker-образа. Один должен компилировать Java-проект обратно в папку на компьютере подьзователя, а второй забирать скомпилированные классы и исполнять их.
\end{itemize}
\newpage
\printnomenclature[40mm]
\end{document}

View File

@ -1,8 +1,9 @@
\documentclass[j-spec.tex]{subfiles}
\begin{document}
%\setcounter{tocdepth}{3}
\setcounter{section}{1}
\pagestyle{plain}
\sloppy
\tableofcontents
\section{Специализация: данные и функции}
\subsection{В предыдущем разделе}
@ -20,9 +21,9 @@
\begin{itemize}
\item \nom{Метод}{функция в языке программирования, принадлежащая классу};
\item \nom{Типизация}{классификация по типам};
\item \nom{Переполнение}{целочисленное переполнение (англ. integer overflow) — ситуация в компьютерной арифметике, при которой вычисленное в результате операции значение не может быть помещено в тип данных};
\item \nom{Переполнение}{целочи́сленное переполне́ние (англ. integer overflow) — ситуация в компьютерной арифметике, при которой вычисленное в результате операции значение не может быть помещено в тип данных};
\item \nom{Инициализация}{одновременной объявление переменной и присваивание ей значения};
\item \nom{Идентификатор}{идентификатор переменной -- название переменной, по которому возможно получить доступ к области памяти, соответствующей этой переменной};
\item \nom{Идентификатор}{идентификатор переменной - название переменной, по которому возможно получить доступ к области памяти, соответствующей этой переменной};
\item \nom{Typecasting}{преобразование типов переменных в типизированных языках программирования};
\item \nom{Массив}{структура данных, хранящая набор значений в непрерывной области памяти};
\end{itemize}
@ -39,26 +40,26 @@
\end{frm}
\begin{itemize}
\item Статическая -- у каждой переменной должен быть тип, и этот тип изменить нельзя. Этому свойству противопоставляется динамическая типизация.
\item Явная -- при создании переменной ей обязательно необходимо присвоить какой-то тип, явно написав это в коде. В более поздних версиях языка (с девятой) стало возможным инициализировать переменные типа \code{var}, обозначающего нужный тип тогда, когда его возможно однозначно вывести из значения справа\footnote{аналог типа \code{auto} в языке C++}. Бывают языки с неявной типизацией, например, Python.
\item Строгая(сильная) -- невозможно смешивать разнотипные данные. С другой стороны, существует, например, JavaScript, в котором запись \code{2 + true} выдаст результат \code{3}.
\item Статическая - у каждой переменной должен быть тип, и этот тип изменить нельзя. Этому свойству противопоставляется динамическая типизация;
\item Явная - при создании переменной ей обязательно необходимо присвоить какой-то тип, явно написав это в коде. В более поздних версиях языка (с 9й) стало возможным инициализировать переменные типа \code{var}, обозначающий нужный тип тогда, когда его возможно однозначно вывести из значения справа. Бывают языки с неявной типизацией, например, Python;
\item Строгая(сильная) - невозможно смешивать разнотипные данные. С другой стороны, существует JavaScript, в котором запись \code{2 + true} выдаст результат \code{3}.
\end{itemize}
\subsubsection{Антипаттерн «магические числа»}
Почти во всех примерах, которые используются для обучения, можно увидеть так называемый антипаттерн -- плохой стиль для написания кода. Числа, которые находятся справа от оператора присваивания используются в коде без пояснений. Такой антипаттерн называется «магическое число». Магическое, потому что непонятно, что это за число, почему это число именно такое и что будет, если это число изменить.
Почти во всех примерах, которые используются для обучения, можно увидеть так называемый антипаттерн - плохой стиль для написания кода. Числа, которые находятся справа от оператора присваивания используются в коде без пояснений. Такой антипаттерн называется «магическое число». Магическое, потому что непонятно, что это за число, почему это число именно такое и что будет, если это число изменить.
В реальных проектах так лучше не делать. Заранее нужно сказать, что рекомендуется помещать все числа в коде в именованные константы, которые хранятся в начале файла. Плюсом такого подхода является возможность легко корректировать значения переменных в достаточно больших проектах.
Так лучше не делать. Заранее нужно сказать, что рекомендуется помещать все числа в коде в именованные константы, которые хранятся в начале файла. Плюсом такого подхода является возможность легко корректировать значения переменных в достаточно больших проектах.
Например, в вашем коде несколько тысяч строк, а какое-то число, скажем, возраст совершеннолетия, число 18, использовалось несколько десятков раз. При использовании приложения в стране, где совершеннолетием считается 21 год вы должны будете перечитывать весь код в поисках магических «18» и исправить их на «21». В этом вопросе будет также важно не запутаться, действительно ли это 18, которые означают совершеннолетие, а не количество карманов в жилетке Анатолия Вассермана\footnote{мы то знаем, что их 26}.
Например, в вашем коде несколько тысяч строк, а какое-то число, скажем, возраст совершеннолетия, число 18, использовалось несколько десятков раз. При использовании приложения в стране, где совершеннолетием считается $21$ год вы должны будете перечитывать весь код в поисках магических «18» и исправить их на «21». В этом вопросе будет также важно не запутаться, действительно ли это $18$, которые означают совершеннолетие, а не количество карманов в жилетке Анатолия Вассермана\footnote{мы то знаем, что их 26}.
В случае с константой изменить число нужно в одном месте.
\subsection{Примитивные типы данных}
Все данные в Java делятся на две основные категории: примитивные и ссылочные. Таблица \hrf{tab:types} демонстрирует все восемь примитивных типов языка и их размерности. Чтобы отправить на хранение какие-то данные используется оператор присваивания. Присваивание в программировании -- это не тоже самое, что математическое равенство, демонстрирующее тождественность, а полноценная операция.
Все данные в Java делятся на две основные категории: примитивные и ссылочные. Таблица \hrf{tab:types} демонстрирует все восемь примитивных типов языка и их размерности. Чтобы отправить на хранение какие-то данные используется оператор присваивания. Присваивание в программировании - это не тоже самое, что математическое равенство, демонстрирующее тождественность, а полноценная операция.
Все присваивания всегда происходят справа налево, то есть сначала вычисляется правая часть, а потом результат вычислений присваивается левой. Исключений нет, именно поэтому в левой части не может быть никаких вычислений.
\begin{table}[H]
\begin{table}
\centering
\begin{tabular}{|p{17mm}|p{80mm}|p{55mm}|}
\hline
@ -85,20 +86,16 @@
\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/}{расследование} крушения ракеты из-за переполнения переменной)
Чем именно чревато переполнение переменной легче показать на примере (по ссылке - \href{https://habr.com/ru/company/pvs-studio/blog/306748/}{расследование} крушения ракеты из-за переполнения переменной)
\begin{frm} \excl Переполнение переменных не распознаётся компилятором. \end{frm}
Если создать переменную типа \code{byte}, диапазон которого от $[-128, +127]$, и присвоить этой переменной значение $200$ произойдёт переполнение, как если попытаться влить пакет молока в напёрсток.
Если создать переменную типа byte, диапазон которого от $[-128, +127]$, и присвоить этой переменной значение $200$ произойдёт переполнение, как если попытаться влить пакет молока в напёрсток.
\begin{frm} \info Переполнение переменной -- это ситуация, в которой происходит попытка положить большее значение в переменную меньшего типа. \end{frm}
\begin{frm} \info Переполнение переменной - это ситуация, в которой происходит попытка положить большее значение в переменную меньшего типа. \end{frm}
Важным вопросом при переполнении остаётся следующий: какое в переполненной переменной останется значение? Максимальное, $127$? $200 - 127 = 73$? Какой-то мусор? Каждый язык, а зачастую и разные компиляторы одного языка ведут себя в этом вопросе по разному.
@ -113,13 +110,13 @@
\subsubsection{Задание для самопроверки}
\begin{enumerate}
\item Возможно ли объявить в Java целочисленную переменную и присвоить ей дробное значение?
\item Магическое число -- это:
\item Магическое число - это:
\begin{enumerate}
\item числовая константа без пояснений;
\item число, помогающее в вычислениях;
\item числовая константа, присваиваемая при объявлении переменной.
\end{enumerate}
\item Переполнение переменной -- это:
\item Переполнение переменной - это:
\begin{enumerate}
\item слишком длинное название переменной;
\item слишком большое значение переменной;
@ -128,11 +125,11 @@
\end{enumerate}
\subsubsection{Бинарное (битовое) представление данных}
После информации о переполнении, нельзя не сказать о том, что именно переполняется. Далее будут представлены сведения которые касаются не только языка Java но и любого другого языка программирования. Эти сведения помогут разобраться в деталях того как хранится значение переменной в программе и как, в целом, происходит работа компьютерной техники.
После разговора о переполнении, нельзя не сказать о том, что именно переполняется. Далее будут представлены сведения которые касаются не только языка Java но и любого другого языка программирования. Эти сведения помогут разобраться в деталях того как хранится значение переменной в программе и как, в целом, происходит работа компьютерной техники.
\begin{frm} \info Все современные компьютеры, так или иначе работают от электричества и являются примитивными по своей сути устройствами, которые понимают только два состояния: есть напряжение в электрической цепи или нет. Эти два состояния принято записывать в виде 1 и 0, соответственно. \end{frm}
Все данные в любой программе -- это единицы и нули. Данные в программе на Java не исключение, удобнее всего это явление рассматривать на примере примитивных данных. Поскольку в компьютере можно оперировать только двумя значениями то естественным образом используется двоичная система счисления.
Все данные в любой программе - это единицы и нули. Данные в программе на Java не исключение, удобнее всего это явление рассматривать на примере примитивных данных. Поскольку в компьютере можно оперировать только двумя значениями то естественным образом используется двоичная система счисления.
\begin{table}[H]
\centering
@ -166,21 +163,21 @@
Двоичная система счисления это система счисления с основанием два. Существуют и другие системы счисления, например, восьмеричная, но сейчас она отходит на второй план полностью уступая своё место шестнадцатеричной системе счисления. Каждая цифра в десятичной записи числа называется разрядом, аналогично в двоичной записи чисел каждая цифра тоже называется разрядом, но для компьютерной техники этот разряд называется битом.
\begin{frm}
\info Одна единица или ноль -- это один \textbf{бит} передаваемой или хранимой информации.
\info Одна единица или ноль - это один \textbf{бит} передаваемой или хранимой информации.
\end{frm}
Биты принято собирать в группы по восемь штук, по восемь разрядов, эти группы называются \textbf{байт}. В языке Java возможно оперировать минимальной единицей информации, такой как байт для этого есть соответствующий тип. Диапазон байта, согласно таблицы $[-128, +127]$, то есть байт информации может в себе содержать ровно 256 значений. Само число $127$ в двоичной записи это семиразрядное число, все разряды которого единицы (то есть байт выглядит как \code{01111111}). Последний, восьмой, самый старший бит, определяет знак числа\footnote{Для более детального понимания данной темы желательно ознакомиться с информацией о цифровой схемотехнике и хранении отрицательных чисел с применением техники дополнительного кода.}. Для нас достаточно знать формулу расчёта записи отрицательных значений:
Биты принято собирать в группы по восемь штук, по восемь разрядов, эти группы называются \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 бита хранения информации.
Числа б\'{о}льших разрядностей могут хранить б\'{о}льшие значения, теперь преобразование диапазонов из десятичной системы счисления в двоичную покажет что \code{byte} это один байт, \code{short} это два байта, то есть 16 бит, \code{int} это 4 байта то есть 32 бита, а \code{long} это 8 байт или 64 бита хранения информации.
\subsubsection{Задания для самопроверки}
\begin{enumerate}
\item Возможно ли число 3000000000 (три миллиарда) записать в двоичном представлении?
\item Возможно ли число 3000000000 (3 миллиарда) записать в двоичном представлении?
\item Как вы думаете, почему шестнадцатеричная система счисления вытеснила восьмеричную?
\end{enumerate}
@ -192,11 +189,11 @@
Значения в целочисленных типах могут быть только целые, никак и никогда невозможно присвоить им дробных значений. Про эти типы следует помнить следующее:
\begin{itemize}
\item \code{int} -- это самый часто используемый тип. Если сомневаетесь, какой целочисленный тип использовать, используйте \code{int};
\item все целые числа, которые пишутся в коде -- это \code{int}, даже если вы пытаетесь их присвоить переменной другого типа.
\item \code{int} - это самый часто используемый тип. Если сомневаетесь, какой целочисленный тип использовать, используйте \code{int};
\item все целые числа, которые пишутся в коде - это \code{int}, даже если вы пытаетесь их присвоить переменной другого типа.
\end{itemize}
Как \code{int} преобразуется в меньше типы? Если написать цифрами \textit{справа} число, которое может поместиться в переменную меньшего типа \textit{слева}, то статический анализатор кода его пропустит, а компилятор преобразует в меньший тип автоматически (строка 9 на рис. \hrf{pic:byte-overflow}).
Как \code{int} преобразуется в меньше типы? Если написать цифрами справа число, которое может поместиться в переменную меньшего типа слева, то статический анализатор кода его пропустит, а компилятор преобразует в меньший тип автоматически (строка 9 на рис. \hrf{pic:byte-overflow}).
\begin{figure}[H]
\centering
\includegraphics[width=12cm]{jc-02-byte-overflow.png}
@ -204,7 +201,7 @@
\label{pic:byte-overflow}
\end{figure}
Как видно, к маленькому \code{byte} успешно присваивается \code{int}. Если же написать число которое больше типа слева и, соответственно, поместиться не может, среда разработки выдает предупреждение компилятора, что ожидался \code{byte}, а передан \code{int} (строка 10 рис. \hrf{pic:byte-overflow}).
Как видно, к маленькому \code{byte} успешно присваивается \code{int}. Если же написать число которое больше типа слева и, соответственно, поместиться не может, среда разработки выдает предупреждение компилятора, что ожидался \code{byte}, а передан \code{int} (строка 10 рис \hrf{pic:byte-overflow}).
Часто нужно записать в виде числа какое-то значение большее чем может принимать \code{int}, и явно присвоить начальное значение переменной типа \code{long}.
@ -215,7 +212,7 @@
\label{pic:int-overflow}
\end{figure}
В примере на рис. \hrf{pic:int-overflow} показана попытка присвоить значение 5000000000 (пять миллиардов) переменной типа \code{long}. Из текста ошибки ясно, что невозможно положить такое большое значение в переменную типа \code{int}, а это значит, что справа \code{int}. Почему большой \code{int} без проблем присваивается к маленькому байту?
В примере на рис. \hrf{pic:int-overflow} показана попытка присвоить значение 5000000000 переменной типа \code{long}. Из текста ошибки ясно, что невозможно положить такое большое значение в переменную типа \code{int}, а это значит, что справа \code{int}. Почему большой \code{int} без проблем присваивается к маленькому байту?
\begin{figure}[H]
\centering
@ -224,16 +221,12 @@
\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}
На рис. \hrf{pic:overflow-solution} продемонстрировано, что аналогичная ситуация возникает с типами \code{float} и \code{double}. Все дробные числа, написанные в коде - это \code{double}, поэтому положить их во \code{float} без дополнительных усилий невозможно. В этих случаях к написанному справа числу нужно добавить явное указание на его тип. Для \code{long} пишем \code{L}, а для \code{float} - \code{f}. Чаще всего \code{L} пишут заглавную, чтобы подчеркнуть, что тип больше, а \code{f} пишут маленькую, чтобы подчеркнуть, что мы уменьшаем тип. Но регистр в этом конкретном случае значения не имеет, можно писать и так и так.
\subsubsection{Числа с плавающей запятой (точкой)}
Как видно из таблицы \hrf{tab:types}, два из восьми типов не имеют диапазонов значений. Это связано с тем, что диапазоны значений \code{float} и \code{double} заключаются не в величине возможных хранимых чисел, а в точности этих чисел после запятой.
Как видно из таблицы \hrf{tab:types}, два из восьми типов не имеют диапазонов значений. Это связано с тем, что диапазоны значений флоута и дабла заключаются не в величине возможных хранимых чисел, а в точности этих чисел после запятой.
\begin{frm} \info Числа с плавающей запятой в англоязычной литературе называются числа с плавающей точкой (от англ. floating point). Такое различие связано с тем, что в русскоязычной литературе принято отделять дробную часть числа запятой, а в европейской и американской -- точкой. \end{frm}
\begin{frm} \info Числа с плавающей запятой в англоязычной литературе называются числа с плавающей точкой (от англ. floating point). Такое различие связано с тем, что в русскоязычной литературе принято отделять дробную часть числа запятой, а в европейской и американской - точкой. \end{frm}
Хранение чисел с плавающей запятой\footnote{хорошо и подробно, но на С, в посте на \href{https://habr.com/ru/post/112953/}{Хабре}.} работает по стандарту IEEE 754 (1985 г). Для работы с числами с плавающей запятой на аппаратурном уровне к обычному процессору добавляют математический сопроцессор (FPU, floating point unit).
@ -241,16 +234,14 @@
\centering
\begin{subfigure}[b]{0.48\textwidth}
\centering
\def\svgwidth{\textwidth}
\includesvg{pics/jc-02-float-struct.svg}
\includesvg[width=\textwidth]{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}
\includesvg[width=\textwidth]{pics/jc-02-float-struct32.svg}
\caption{float}
\label{pic:float-float}
\end{subfigure}
@ -258,7 +249,7 @@
\label{pic:float-struct}
\end{figure}
Рисунок \hrf{pic:float-struct} демонстрирует, как распределяются биты в числах с плавающей запятой разных разрядностей, где S -- Sign (знак), E -- Exponent, 8 (или 11) разрядов поля порядка, экспонента, M -- Mantissa, 23 (или 52) бита мантиссы, дробная часть числа. Также на рисунке показана так называемая, мнимая единица, она всегда есть в самом старшем разряде мантиссы, поэтому её всегда подразумевают, но в явном виде не хранят, экономя один бит информации.
Рисунок \hrf{pic:float-struct} демонстрирует, как распределяются биты в числах с плавающей запятой разных разрядностей, где S - Sign (знак), E - Exponent (8(11) разрядов поля порядка, экспонента), M - Mantissa (23(52) бита мантиссы, дробная часть числа).
Если попытаться уложить весь стандарт в два предложения, то получится примерно следующее: получить число в соответствующих разрядностях возможно по формулам:
\begin{equation*}
@ -282,7 +273,7 @@
Отсюда становится очевидно, что чем сложнее мантисса и чем меньше порядок, тем более точные и интересные числа мы можем получить.
\end{frm}
Возьмём для примера число $-0,15625$, чтобы понять как его записывать, откинем знак, это будет единица в разряде, отвечающем за знак, и посчитаем мантиссу с порядком. Представим число как положительное и будем от него последовательно отнимать числа, являющиеся отрицательными степенями двойки, чтобы получить максимально близкое к нулю значение, но не превысить его.
Возьмём для примера число $-0,15625$, чтобы понять как его записывать, откинем знак, это будет единица в разряде, отвечающем за знак, и посчитаем мантиссу с порядком. Представим число как положительное и будем от него последовательно отнимать числа, являющиеся отрицательными степенями двойки, чтобы получить максимально близкое к нулю значение.
\begin{equation*}
\begin{gathered}
@ -292,16 +283,17 @@
Очевидно, что $-1$ и $-2$ степени отнять не получится, поскольку мы явно уходим за границу нуля, а вот $-3$ прекрасно отнимается, значит порядок будет $127-3 = 124$, осталось понять, что получится в мантиссе.
Видим, что оставшееся после первого вычитания ($0,15625 - 0,125$) число -- это $2^{-5}$. Значит в мантиссе пишем \code{01} и остальные нули, то есть слева направо указываем, какие степени после $-3$ будут нужны. $-4$ не нужна, а $-5$ нужна.
Видим, что оставшееся после первого вычитания ($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 \\
(-1)^1 \times 2^{(124-127)} \times (1 + \frac{2097152}{2^{23}}) = 1,15652 \\
\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
(-1)^1 \times 1,01e-3 = \\
1\times2^{-3} + 0\times2^{-4} + 1\times2^{-5} = \\
1\times0,125 + 0\times0,0625 + 1\times0,03125 = \\
0,125 + 0,03125 = 0,15625
\end{gathered}
\end{equation*}
@ -328,7 +320,7 @@
\item Почему нельзя напрямую сравнивать целочисленные данные и числа с плавающей запятой, даже если там точно лежит число без дробной части?
\item Внутри переполненной переменной остаётся значение:
\begin{enumerate}
\item переданное -- максимальное для типа;
\item переданное - максимальное для типа;
\item максимальное для типа;
\item не определено.
\end{enumerate}
@ -383,30 +375,24 @@
\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} строки, а в строки числа.
Тип \code{char} единственный беззнаковый целочисленный тип в языке, то есть его старший разряд хранит полезное значение, а не признак положительности. Тип целочисленный но по умолчанию среда исполнения интерпретирует его как символ по таблице utf-8 (см фрагмент в таблице \hrf{table:utf-8-ascii}). В языке Java есть разница между одинарными и двойными кавычками. В одинарных кавычках всегда записывается символ, который на самом деле является целочисленным значением, а в двойных кавычках всегда записывается строка, которая фактически является экземпляром класса \code{String}. Поскольку типизация строгая, то невозможно записать в \code{char} строки, а в строки числа.
\begin{frm} \info В Java есть три основных понятия, связанных с данными переменными и использованием значений: объявление, присваивание, инициализация.
Для того чтобы \textit{объявить} переменную, нужно написать её тип и название, также часто вместо названия можно встретить термин идентификатор.
Далее в любой момент можно \textit{присвоить} этой переменной значение, то есть необходимо написать идентификатор, использовать оператор присваивания, и справа написать значение, которое вы хотите присвоить данной переменной. Поставить в конце строки точку с запятой.
Далее в любой момент можно \textit{присвоить} этой переменной значение, то есть необходимо написать идентификатор использовать оператор присваивания и справа написать значение, которое вы хотите присвоить данной переменной, поставить в конце строки точку с запятой.
Также существует понятие \textit{инициализации} -- это когда объединяются на одной строке объявление и присваивание.\end{frm}
Также существует понятие \textit{инициализации} - это когда объединяются на одной строке объявление и присваивание.\end{frm}
\subsubsection{Преобразование типов}
Java - это язык со строгой статической типизацией, но преобразование типов в ней всё равно есть. Простыми словами, преобразование типов -- это когда компилятор видит, что типы переменных по разные стороны присваивания разные, начинает разрешать это противоречие, успешно или нет. Преобразование типов бывает явное и неявное. Неявное преобразование типов происходит когда компилятор в состоянии сам преобразовать типы, явное, когда ему нужна помощь.
Java - это язык со строгой статической типизацией, но преобразование типов в ней всё равно есть. Простыми словами, преобразование типов - это когда компилятор видит, что типы переменных по разные стороны присваивания разные, начинает разрешать это противоречие. Преобразование типов бывает явное и неявное.
\begin{frm}
\info В разговоре или в сообществах можно услышать или прочитать термины тайпкастинг, кастинг, каст, кастануть, и другие производные от английского typecasting.
\end{frm}
Неявное преобразование типов происходит, когда присваиваются числа переменным меньшей размерности, чем \code{int}. Число справа это \code{int}, а значит 32 разряда, а слева, например, \code{byte}, и в нём всего 8 разрядов, но ни среда ни компилятор не «поругались», потому что значение в большом \code{int} не превысило 8 разрядов маленького \code{byte}. Итак неявное преобразование типов происходит в случаях, когда, «всё и так понятно». В случае, если неявное преобразование невозможно, статический анализатор кода выдаёт ошибку, что ожидался один тип, а был дан другой.
Неявное преобразование типов происходит, когда присваиваются числа переменным меньшей размерности, чем \code{int}. Число справа это \code{int}, а значит 32 разряда, а слева, например, \code{byte}, и в нём всего 8 разрядов, но ни среда ни компилятор не поругались, потому что значение в большом \code{int} не превысило 8 разрядов маленького \code{byte}. Итак неявное преобразование типов происходит в случаях, когда, «всё и так понятно». В случае, если неявное преобразование невозможно, статический анализатор кода выдаёт ошибку, что ожидался один тип, а был дан другой.
Явное преобразование типов происходит, когда мы явно пишем в коде, что некоторое значение должно иметь определённый тип. Этот вариант приведения типов тоже был рассмотрен, когда к числам дописывались типовые квалификаторы \code{L} и \code{f}. Но чаще всего случается, что происходит присваивание переменным не тех значений, которые были написаны в тексте программы, а те, которые получились в результате каких-то вычислений.
\begin{figure}[H]
@ -421,33 +407,33 @@ Java - это язык со строгой статической типизац
\centering
\includegraphics[width=12cm]{jc-02-byte-cast-fix.png}
\caption{Верное приведение типов}
\label{pic:byte-cast-error}
\label{pic:byte-cast-fix}
\end{figure}
\subsubsection{Константность}
Constare -- (лат. стоять твёрдо). Константность это свойство неизменяемости. В Java ключевое слово \code{const} не реализовано, хоть и входит в список ключевых, зарезервированных. Константы создаются при помощи ключевого слова \code{final}. Ключевое слово \code{final} возможно применять не только с примитивами, но и со ссылочными типами, методами, классами.
Constare - (лат. стоять твёрдо). Константность это свойство неизменяемости. В Java ключевое слово \code{const} не реализовано, хоть и входит в список ключевых, зарезервированных. Константы создаются при помощи ключевого слова \code{final}. Ключевое слово файнал возможно применять не только с примитивами, но и со ссылочными типами, методами, классами.
\begin{frm}
\info Константа -- это переменная или идентификатор с конечным значением.
\info Константа - это переменная или идентификатор с конечным значением.
\end{frm}
\subsubsection{Задания для самопроверки}
\begin{enumerate}
\item Какая таблица перекодировки используется для представления символов?
\item Каких действий требует от программиста явное преобразование типов?
\item какое значение будет содержаться в переменной a после выполнения строки \code{int а = 10.0f/3.0f;}
\item какое значение будет содержаться в переменной a после выполнения строки int а = 10.0f/3.0f;
\end{enumerate}
\subsection{Ссылочные типы данных, массивы}
Ссылочные типы данных -- это все типы данных, кроме восьми перечисленных примитивных. Самым простым из ссылочных типов является массив. Фактически, массив выведен на уровень языка и не имеет специального ключевого слова.
Ссылочные типы данных - это все типы данных, кроме восьми перечисленных примитивных. Самым простым из ссылочных типов является массив. Фактически массив выведен на уровень языка и не имеет специального ключевого слова.
Ссылочные типы отличаются от примитивных местом хранения информации. В \textit{примитивах} данные хранятся там, где существует переменная и где написан её идентификатор, а по идентификатору \textit{ссылочного} типа хранится не значение, а ссылка. Ссылку можно представить как ярлык на рабочем столе, то есть, очевидно, что непосредственная информация хранится не там, где написан идентификатор. Такое явное разделение идентификатора переменной и данных важно помнить и понимать при работе с ООП.
Ссылочные типы отличаются от примитивных местом хранения информации. В примитивах данные хранятся там, где существует переменная и где написан её идентификатор, а по идентификатору ссылочного типа хранится не значение, а ссылка. Ссылку можно представить как ярлык на рабочем столе, то есть очевидно, что непосредственная информация хранится не там, где написан идентификатор. Такое явное разделение идентификатора переменной и данных важно помнить и понимать при работе с ООП.
\begin{frm} \info \textbf{Массив} -- это единая, сплошная область данных, в связи с чем в массивах возможно осуществление доступа по индексу \end{frm}
\begin{frm} \info \textbf{Массив} - это единая, сплошная область данных, в связи с чем в массивах возможно осуществление доступа по индексу \end{frm}
Самый младший индекс любого массива -- \textit{ноль}, поскольку \textbf{индекс} -- это значение смещения по элементам относительно начального адреса массива. То есть, для получения самого первого элемента нужно сместиться на ноль шагов. Очевидно, что самый последний элемент в массиве из десяти значений, будет храниться по \textit{девятому} индексу.
Самый младший индекс любого массива - ноль, поскольку \textbf{индекс} - это значение смещения по элементам относительно начального адреса массива. То есть, для получения самого первого элемента нужно сместиться на ноль шагов. Очевидно, что самый последний элемент в массиве из десяти значений, будет храниться по девятому индексу.
Массивы возможно создавать несколькими способами (листинг \hrf{lst:array-init}). В общем виде объявление -- это тип, квадратные скобки как обозначение того, что это будет массив из переменных этого типа, идентификатор (строка \hrf{codeline:arr-define}). Инициализировать массив можно либо ссылкой на другой массив (строка \hrf{codeline:arr-link}), пустым массивом (строка \hrf{codeline:arr-new}) или заранее заданными значениями, записанными через запятую в фигурных скобках (строка \hrf{codeline:arr-values}). Присвоить в процессе работы идентификатору возможно только значение ссылки из другого идентификатора или новый пустой массив.
Массивы возможно создавать несколькими способами (листинг \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} @>
@ -455,18 +441,16 @@ Constare -- (лат. стоять твёрдо). Константность эт
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} @>
array2 = {1, 2, 3, 4, 5}; // <@%\lh{dkgreen}{<-- здесь недопустима инициализация}@> <@ \label{codeline:arr-invalid} @>
\end{lstlisting}
Если мы не определяем переменную, понятно, данные мы хранить не планируем. Если определяем примитивную, помним, она инициализируется нулём, а если мы определяем ссылочный идентификатор, он имеет начальное значение \code{null}, то есть явно демонстрирует, что не ссылается ни на какой объект. \textbf{Нулевой указатель} -- это гораздо более серьёзное явление, чем просто временное отсутствие объекта по идентификатору, очень часто это не инициализированные объекты и попытки вызова невозможных методов. Поэтому в работе очень часто помогает понять, что именно пошло не так \code{NullPointerException}.
\begin{frm} \excl Никак и никогда нельзя присвоить идентификатору целый готовый массив в процессе работы, нельзя стандартными средствами переприсвоить ряд значений части массива (так называемые слайсы или срезы). \end{frm}
\begin{frm} \excl Никак и никогда нельзя присвоить идентификатору целый готовый массив (создаваемый здесь и сейчас) в процессе работы, нельзя стандартными средствами переприсвоить ряд значений части массива (так называемые слайсы или срезы). \end{frm}
Массивы бывают как одномерные, так и многомерные. Многомерный массив -- это всегда массив из массивов меньшего размера: двумерный массив -- это массив одномерных, трёхмерный -- массив двумерных и так далее. Правила инициализации у них не отличаются. Преобразовать тип массива нельзя никогда, но можно преобразовать тип каждого отдельного элемента при чтении. Это связано с тем, что под массивы сразу выделяется непрерывная область памяти, а со сменой типа всех значений массива эту область нужно будет или значительно расширять или значительно сужать.
Массивы бывают как одномерные, так и многомерные. Многомерный массив - это всегда массив из массивов меньшего размера: двумерный массив - это массив одномерных, трёхмерный - массив двумерных и так далее. Правила инициализации у них не отличаются. Преобразовать тип массива нельзя никогда, но можно преобразовать тип каждого отдельного элемента при чтении. Это связано с тем, что под массивы сразу выделяется непрерывная область памяти, а со сменой типа всех значений массива эту область нужно будет или значительно расширять или значительно сужать.
Ключевое слово \code{final} работает только с идентификатором массива, то есть не запрещает изменять значения его элементов.
Если алгоритм приложения предполагает создание нижних измерений массива в процессе работы программы, то при инициализации массива верхнего уровня не следует указывать размерности нижних уровней. Это связано с тем, что при инициализации, Java сразу выделяет память под все измерения, а присваивание нижним измерениям новых ссылок на создаваемые в процессе работы массивы, будет пересоздавать области памяти, получается небольшая утечка памяти.
Если логика программы предполагает создание нижних измерений массива в процессе работы программы, то при инициализации массива верхнего уровня не следует указывать размерности нижних уровней. Это связано с тем, что при инициализации, Java сразу выделяет память под все измерения, а присваивание нижним измерениям новых ссылок на создаваемые в процессе работы массивы, будет пересоздавать области памяти, получается небольшая утечка памяти.
Прочитать из массива значение возможно обратившись к ячейке массива по индексу. Записать в массив значение возможно обратившись к ячейке массива по индексу, и применив оператор присваивания.
\begin{lstlisting}[language=Java,style=JCodeStyle]
@ -492,12 +476,12 @@ Constare -- (лат. стоять твёрдо). Константность эт
\subsection{Базовый функционал языка}
\subsubsection{Математические операторы}
Математические операторы работают как и предполагается -- складывают, вычитают, делят, умножают, делают это по приоритетам, известным нам с пятого класса, а если приоритет одинаков -- слева направо. Специального оператора возведения в степень как в Python нет. Единственное, что следует помнить, что оператор присваивания продолжает быть оператором присваивания, а не является математическим тождеством, а значит сначала посчитается всё, что слева, а потом результат попробует присвоиться переменной справа. Припоминаем какие есть особенности у операции целочисленного деления, связанные с отбрасыванием дробной части.
Математические операторы работают как и предполагается - складывают, вычитают, делят, умножают, делают это по приоритетам известным нам с пятого класса, а если приоритет одинаков - слева направо. Специального оператора возведения в степень как в пайтоне нет. Единственное, что следует помнить, что оператор присваивания продолжает быть оператором присваивания, а не является математическим равенством, а значит сначала посчитается всё, что слева, а потом результат попробует присвоиться переменной справа. Припоминаем что там за дела с целочисленным делением и отбрасыванием дробной части.
\subsubsection{Условия}
Условия представлены в языке привычными \code{if}, \code{else if}, \code{else}, «если», «иначе если», «в противном случае», которые являются единым оператором выбора, то есть, если исполнение программы пошло по одной из веток, то в другую ветку условия программа никогда не зайдёт. Каждая ветвь условного оператора -- это отдельный кодовый блок со своим окружением и локальными переменными.
Условия представлены в языке привычными \code{if}, \code{else if}, \code{else}, «если», «иначе если», «в противном случае», которые являются единым оператором выбора, то есть если исполнение программы пошло по одной из веток, то в другую ветку условия программа точно не зайдёт. Каждая ветвь условного оператора - это отдельный кодовый блок со своим окружением и локальными переменными.
Существует альтернатива оператору \code{else if} -- использование оператора \code{switch}, который позволяет осуществлять множественный выбор между числовыми значениями. У оператора есть ряд особенностей:
Существует альтернатива оператору \code{else if} - использование оператора \code{switch}, который позволяет осуществлять множественный выбор между числовыми значениями. У оператора есть ряд особенностей:
\begin{itemize}
\item это оператор, состоящий из одного кодового блока, то есть сегменты кода находятся в одной области видимости. Если не использовать оператор \code{break}, есть риск «проваливаться» в следующие кейсы;
\item нельзя создать диапазон значений;
@ -512,12 +496,12 @@ Constare -- (лат. стоять твёрдо). Константность эт
\item \code{for (;;) {}}
\end{itemize}
Цикл -- это набор повторяющихся до наступления условия действий. \code{while} -- самый простой, чаще всего используется, когда нужно описать бесконечный цикл. \code{do-while} единственный цикл с постусловием, то есть сначала выполняется тело, а затем принимается решение о необходимости зацикливания, используется для ожидания ответов на запрос и возможного повторения запроса по условию. \code{for} -- классический счётный цикл, его почему-то программисты любят больше всего.
Цикл - это набор повторяющихся до наступления условия действий. \code{while} - самый простой, чаще всего используется, когда нужно описать бесконечный цикл. \code{do-while} единственный цикл с постусловием, то есть сначала выполняется тело, а затем принимается решение о необходимости зацикливания, используется для ожидания ответов на запрос и возможного повторения запроса по условию. \code{for} - классический счётный цикл, его почему-то программисты любят больше всего.
Существует также активно пропагандируемый цикл -- \code{foreach}, работает не совсем очевидным образом, для понимания его работы необходимо ознакомиться с ООП и понятием итератора.
Существует также активно пропагандируемый цикл - \code{foreach}, работает не совсем очевидным образом, для понимания его работы необходимо ознакомиться с ООП и понятием итератора.
\subsubsection{Бинарные арифметические операторы}
В современных реалиях мегамощных компьютеров вряд ли кто-то задумывается об оптимизации скорости выполнения программы или экономии занимаемой памяти. Но всё меняется, когда программист впервые принимает сложное решение: запрограммировать микроконтроллер или другой «интернет вещей». Там в вашем распоряжении пара сотен килобайт памяти, если очень повезёт, в которые нужно не только как-то вложить текст программы и исполняемый бинарный код, но и какие-то промежуточные, пользовательские и другие данные, буферы обмена и обработки. Другая ситуация, в которой нужно начинать «думать о занимаемом пространстве» это разработка протоколов передачи данных, чтобы протокол был быстрый, не передавал по сети большие объёмы данных и быстро преобразовывался. На помощь приходит натуральная для информатики система счисления, двоичная.
В современных реалиях мегамощных компьютеров вряд ли кто-то задумывается об оптимизации скорости выполнения программы или экономии занимаемой памяти. Но всё меняется, когда программист впервые принимает сложное решение: запрограммировать микроконтроллер или другой «интернет вещей». Там в вашем распоряжении жалкие пара сотен килобайт памяти, если очень повезёт, в которые нужно не только как-то вложить текст программы и исполняемый бинарный код, но и какие-то промежуточные, пользовательские и другие данные, буферы обмена и обработки. Другая ситуация, в которой нужно начинать «думать о занимаемом пространстве» это разработка протоколов передачи данных, чтобы протокол был быстрый, не передавал по сети большие объёмы данных и быстро преобразовывался. На помощь приходит натуральная для информатики система счисления, двоичная.
Манипуляции двоичными данными представлены в Джава следующими операторами:
\begin{itemize}
@ -531,7 +515,7 @@ Constare -- (лат. стоять твёрдо). Константность эт
Литеральные «и», «или», «не» уже знакомы по условным операторам. Литеральные операции применяются ко всему числовому литералу целиком, а не к каждому отдельному биту. Их особенность заключается в том, как язык программирования интерпретирует числа.
\begin{frm} \info В Java в литеральных операциях может участвовать только тип \code{boolean}, в то время, как, например, C++ воспринимает любой ненулевой целочисленный литерал как истину, а нулевой, соответственно, как ложь.
\begin{frm} \info В Java в литеральных операциях может участвовать только тип \code{boolean}, а C++ воспринимает любой ненулевой целочисленный литерал как истину, а нулевой, соответственно, как ложь.
\end{frm}
Логика формирования значения при этом остаётся такой же, как и при битовых операциях.
@ -583,7 +567,8 @@ Constare -- (лат. стоять твёрдо). Константность эт
\label{table:bin-truth-tables}
\end{table}
Когда говорят о битовых операциях, так или иначе, появляется необходимость поговорить о таблицах истинности. В таблице \hrf{table:bin-truth-tables} вы видите таблицы истинности для арифметических битовых операций. Битовые операции отличаются тем, что для неподготовленного взгляда они производят почти магические действия, потому что манипулируют двоичным представлением числа.
Когда говорят о битовых операциях волей-неволей появляется необходимость поговорить о таблицах истинности. В таблице \hrf{table:bin-truth-tables} вы видите таблицы истинности для арифметических битовых операций. Битовые операции отличаются тем, что для неподготовленного взгляда они производят почти магические действия, потому что манипулируют двоичным представлением числа.
\begin{figure}[H]
\begin{arithmetic}
@ -618,45 +603,45 @@ Constare -- (лат. стоять твёрдо). Константность эт
\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} \\
2 & 000000010 & \code{2 << 0} \\
4 & 000000100 & \code{2 << 1} \\
8 & 000001000 & \code{2 << 2} \\
16 & 000010000 & \code{2 << 3} \\
32 & 000100000 & \code{2 << 4} \\
64 & 001000000 & \code{2 << 5} \\
128 & 010000000 & \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} \\
128 & 010000000 & \code{128 >> 0} \\
64 & 001000000 & \code{128 >> 1} \\
32 & 000100000 & \code{128 >> 2} \\
16 & 000010000 & \code{128 >> 3} \\
8 & 000001000 & \code{128 >> 4} \\
4 & 000000100 & \code{128 >> 5} \\
2 & 000000010 & \code{128 >> 6} \\
\hline
\end{tabular}
\caption{Битовые сдвиги}
\label{table:bit-shift}
\end{table}
С битовыми сдвигами работать гораздо интереснее и выгоднее. Они производят арифметический сдвиг значения слева на количество разрядов, указанное справа, в таблице \hrf{table:bit-shift} представлены восьмиразрядные беззнаковые числа, в битовом представлении это одна единственная единица, находящаяся в разных разрядах числа. Это демонстрация сдвига на один разряд влево, и, как следствие, умножение на два. Обратная ситуация со сдвигом вправо, он является целочисленным делением.
С битовыми сдвигами работать гораздо интереснее и выгоднее. Они производят арифметический сдвиг значения слева на количество разрядов, указанное справа, в таблице \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.
\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}
@ -668,10 +653,10 @@ Constare -- (лат. стоять твёрдо). Константность эт
\end{enumerate}
\subsection{Функции}
\textbf{Функция} -- это исполняемый блок кода. Функция, принадлежащая классу называется \textbf{методом}.
\textbf{Функция} - это исполняемый блок кода. Функция, принадлежащая классу называется \textbf{методом}.
\begin{lstlisting}[language=Java,style=JCodeStyle]
void method(int param1, int param2) {
void int method(int param1, int param2) {
//function body
}
@ -680,9 +665,9 @@ Constare -- (лат. стоять твёрдо). Константность эт
}
\end{lstlisting}
При объявлении функции в круглых скобках указываются параметры, а при вызове -- аргументы.
При объявлении функции в круглых скобках указываются параметры, а при вызове - аргументы.
У функций есть правила именования: функция -- это переходный глагол совершенного вида в настоящем времени (вернуть, посчитать, установить, создать), часто снабжаемый дополнением, субъектом действия. Методы в Java пишутся lowerCamelCase. Важно, в каком порядке записаны параметры метода, от этого будет зависеть порядок передачи в неё аргументов. Методы обособлены и их параметры локальны, то есть не видны другим функциям.
У функций есть правила именования: функция - это переходный глагол совершенного вида в настоящем времени (вернуть, посчитать, установить, создать), часто снабжаемый дополнением, субъектом действия. Методы в Java пишутся lowerCamelCase. Важно, в каком порядке записаны параметры метода, от этого будет зависеть порядок передачи в неё аргументов. Методы обособлены и их параметры локальны, то есть не видны другим функциям.
\begin{frm}
\excl Нельзя писать функции внутри других функций.
\end{frm}
@ -691,13 +676,11 @@ Constare -- (лат. стоять твёрдо). Константность эт
Возвращаемые из методов значения появляются в том месте, где метод был вызван. Если будет вызвано несколько методов, то весь контекст исполнения первого метода сохраняется, кладётся (на стек) в стопку уже вызванных методов и процессор идёт выполнять только что вызванный второй метод. По завершении вызванного второго метода, мы снимаем со стека лежащий там контекст первого метода, кладём в него вернувшееся из второго метода значение, если оно есть, и продолжаем исполнять первый метод.
Возвращаемого значения у метода может и не быть, в некоторых языках такие функции и методы называются процедурами, а в Java для них просто придумали специальное возвращаемое значение -- \code{void}. Void (от англ. пустота), интересно отметить, что это не какое-то простое emptyness, а серьёзное масштабное космическое void, чтобы подчеркнуть, что метод совсем ничего точно не возвращает.
\textbf{Вызов метода} - это, по смыслу, тоже самое, что подставить в код сразу его возвращаемое значение.
\textbf{Вызов метода} -- это, по смыслу, тоже самое, что подставить в код сразу его возвращаемое значение.
\textbf{Сигнатура метода} - это имя метода и его параметры. В сигнатуру метода не входит возвращаемое значение. Нельзя написать два метода с одинаковой сигнатурой.
\textbf{Сигнатура метода} -- это имя метода и его параметры. В сигнатуру метода не входит возвращаемое значение. Нельзя написать два метода с одинаковой сигнатурой.
\textbf{Перегрузка методов} -- это механизм языка, позволяющий написать методы с одинаковыми названиями и разными оставшимися частями сигнатуры, чтобы получить единообразие при вызове семантически схожих методов с разнотипными данными.
\textbf{Перегрузка методов} - это механизм языка, позволяющий написать методы с одинаковыми названиями и разными оставшимися частями сигнатуры, чтобы получить единообразие при вызове семантически схожих методов с разнотипными данными.
\subsection*{Практическое задание}
\begin{enumerate}

1193
jtc3-03a.tex Normal file

File diff suppressed because it is too large Load Diff

733
jtc4-04a.tex Normal file
View File

@ -0,0 +1,733 @@
\documentclass[j-spec.tex]{subfiles}
\begin{document}
\setcounter{section}{3}
\setlength{\columnsep}{22pt}
\pagestyle{plain}
\sloppy
\tableofcontents
\section{Специализация: ООП и исключения}
\subsection{В предыдущем разделе}
Была рассмотрена реализация объектно-ориентированного программирования в Java. Рассмотрели классы и объекты, а также наследование, полиморфизм и инкапсуляцию. Дополнительно был освещён вопрос устройства памяти.
\subsection{В этом разделе}
В дополнение к предыдущему, будут разобраны такие понятия, как внутренние и вложенные классы; процессы создания, использования и расширения перечислений. Более детально будет разобрано понятие исключений и их тесная связь с многопоточностью в Java. Будут рассмотрены исключения с точки зрения ООП, процесс обработки исключений.
\begin{itemize}
\item \nom{Перечисление}{это упоминание объектов, объединённых по какому-либо признаку. Фактически, представляет новый тип данных, поэтому возможно определить переменную данного типа и использовать её.};
\item \nom{Внутренний класс}{нестатический класс, объявленный внутри другого класса.};
\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}
\subsection{Перечисления}
Кроме восьми примитивных типов данных и классов в Java есть специальный тип, выведенный на уровень синтаксиса языка -- \code{enum} или перечисление. Перечисления представляют набор логически связанных констант. Объявление перечисления происходит с помощью оператора \code{enum}, после которого идет название перечисления. Затем идет список элементов перечисления через запятую.
\begin{frm} \info Перечисление -- это упоминание объектов, объединённых по какому-либо признаку \end{frm}
Перечисления -- это специальные классы, содержащие внутри себя собственные статические экземпляры.
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Пример перечисления}]
enum Season { WINTER, SPRING, SUMMER, AUTUMN }
\end{lstlisting}
Перечисление, фактически, представляет новый тип данных, поэтому возможно определить переменную данного типа и использовать её. Переменная типа перечисления может хранить любой объект этого исключения.
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Переменная типа перечисления}]
Season current = Season.SPRING;
System.out.println(current);
\end{lstlisting}
Интересно также то, что вывод в терминал и запись в коде у исключений полностью совпадают, поэтому, в результате выполнения этого кода, в терминале будет выведено
\begin{verbatim}
SPRING
\end{verbatim}
Каждое перечисление имеет статический метод \code{values()}, возвращающий массив всех констант перечисления.
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Вывод всех элементов перечисления}]
Season[] seasons = Season.values();
for (Season s : seasons) {
System.out.printf("s ", s);
}
\end{lstlisting}
Именно в этом примере используется цикл foreach для прохода по массиву, для лаконичности записи. Данный цикл берёт последовательно каждый элемент перечисления, присваивает ему имя \code{s} точно также, как это сделано в примере выше, делает эту переменную доступной в теле цикла в рамках одной итерации, на следующей итерации будет взят следующий элемент, и так далее.
\begin{verbatim}
WINTER, SPRING, SUMMER, AUTUMN
\end{verbatim}
Также, в перечисления встроен метод \code{ordinal()}, возвращающий порядковый номер определенной константы (нумерация начинается с 0). Обратите внимание на синтаксис, метод можно вызвать только у конкретного экземпляра перечисления, а при попытке вызова у самого класса перечисления, ожидаемо компилятор выдаёт ошибку невозможности вызова нестатического метода из статического контекста.
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Метод \code{ordinal()}}]
System.out.println(current.ordinal());
System.out.println(Seasons.ordinal()); // <@\lh{dkgreen}{ошибка}@>
\end{lstlisting}
Такое поведение возможно, только если номер элемента хранится в самом объекте.
\begin{frm} \info
В перечислениях можно наблюдать очень примечательный пример инкапсуляции -- неизвестно, хранятся ли на самом деле объекты перечисления в виде массива, но можем вызвать метод values() и получить массив всех элементов перечисления. Неизвестно, хранится ли в каждом объекте перечисления его номер, но можем вызвать его метод \code{ordinal()}.
\end{frm}
Раз перечисление -- это класс, возможно определять в нём поля, методы, конструкторы и прочее. Перечисление \code{Color} определяет приватное поле \code{code} для хранения кода цвета, а с помощью метода \code{getCode} он возвращается.
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Расширение объекта перечисления}]
public class Main {
enum Color {
RED("#FF0000"), BLUE("#0000FF"), GREEN("#00FF00");
private String code;
Color(String code) {
this.code = code;
}
public String getCode(){ return code;}
}
public static void main(String[] args) {
System.out.println(Color.RED.getCode());
System.out.println(Color.GREEN.getCode());
}
}
\end{lstlisting}
Через конструктор передается значение пользовательского поля.
\begin{frm} \excl Конструктор по умолчанию имеет модификатор \code{private}. Любой другой модификатор будет считаться ошибкой.
\end{frm}
Cоздать константы перечисления с помощью конструктора возможно только внутри самого перечисления. И что косвенно намекает на то, что объекты перечисления это статические объекты внутри самого класса перечисления. Также важно, что механизм описания конструкторов класса работает по той же логике, что и обычные конструкторы, то есть, при описании собственного конструктора, конструктор по-умолчанию перестаёт создаваться автоматически. Таким образом, с объектами перечисления можно работать точно также, как с обычными объектами.
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Вывод значений пользовательского поля перечисления}]
for (Color c : Color.values()) {
System.out.printf("s(s)\n", c, c.getCode());
}
\end{lstlisting}
\begin{verbatim}
RED(#FF0000)
BLUE(#0000FF)
GREEN(#00FF00)
\end{verbatim}
\subsubsection{Задания для самопроверки}
\begin{enumerate}
\item Перечисления нужны, чтобы: 3
\begin{enumerate}
\item вести учёт созданных в программе объектов;
\item вести учёт классов в программе;
\item вести учёт схожих по смыслу явлений в программе;
\end{enumerate}
\item Перечисление -- это: 2
\begin{enumerate}
\item массив
\item класс
\item объект
\end{enumerate}
\item каждый объект в перечислении -- это: 3
\begin{enumerate}
\item статическое поле
\item статический метод
\item статический объект
\end{enumerate}
\end{enumerate}
\subsection{Внутренние и вложенные классы}
В Java есть возможность создавать классы внутри других классов, все такие классы разделены на следующие типы:
\begin{enumerate}
\item Non-static nested (inner) classes — нестатические вложенные (внутренние) классы;
\begin{itemize}
\item локальные классы (local classes);
\item анонимные классы (anonymous classes);
\end{itemize}
\item Static nested classes — статические вложенные классы.
\end{enumerate}
Для рассмотрения анонимных классов понадобятся дополнительные знания об интерфейсах, поэтому будут рассмотрены позднее.
\subsubsection{Внутренние классы}
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Вывод значений пользовательского поля перечисления}]
public class Orange {
public void squeezeJuice() {
System.out.println("Squeeze juice ...");
}
class Juice {
public void flow() {
System.out.println("Juice dripped ...");
}
}
}
\end{lstlisting}
\textbf{Внутренние классы} создаются внутри другого класса. Рассмотрим на примере апельсина с реализацией, как это предлагает официальная документация Oracle. В основной программе необходимо создать отдельно апельсин, отдельно его сок через интересную форму вызова конструктора, показанную в листинге \hrf{lst:create-orange}, что позволяет работать как с апельсином, так и его соком по отдельности.
\begin{lstlisting}[language=Java,style=JCodeStyle,label={lst:create-orange},caption={Обычный апельсин Oracle}]
Orange orange = new Orange();
Orange.Juice juice = orange.new Juice();
orange.squeezeJuice();
juice.flow();
\end{lstlisting}
Важно помнить, что когда в жизни апельсин сдавливается, из него сам по себе течёт сок, а когда апельсин попадает к нам в программу он сразу снабжается соком.
\begin{lstlisting}[language=Java,style=JCodeStyle,label={lst:create-gb-orange},caption={Необычный апельсин GeekBrains}]
public class Orange {
private Juice juice;
public Orange() {
this.juice = new Juice();
}
public void squeezeJuice() {
System.out.println("Squeeze juice ...");
juice.flow();
}
private class Juice {
public void flow() {
System.out.println("Juice dripped ...");
}
}
}
\end{lstlisting}
Итак, был создан апельсин, при создании объекта апельсина у него сразу появляется сок. Ниже в классе описано потенциальное наличие у апельсина сока, как его части, поэтому внутри класса апельсин создан класс сока. При создании апельсина создали сок, так или иначе -- самостоятельную единицу, обладающую своими свойствами и поведением, отличным от свойств и поведения апельсина, но неразрывно с ним связанную. При попытке выдавить сок у апельсина -- объект сока сообщил о том, что начал течь
\begin{lstlisting}[language=Java,style=JCodeStyle,label={lst:use-gb-orange},caption={Использование апельсина GeekBrains}]
Orange orange = new Orange();
orange.squeezeJuice();
\end{lstlisting}
Таким образом у каждого апельсина будет свой собственный сок, который возможно выжать, сдавив апельсин. В этом смысл внутренних классов не статического типа -- нужные методы вызываются у нужных объектов.
\begin{frm} \info Такая связь объектов и классов называется композицией. Существуют также ассоциация и агрегация.
\end{frm}
Если класс полезен только для одного другого класса, то часто бывает удобно встроить его в этот класс и хранить их вместе. Использование внутренних классов увеличивает инкапсуляцию. Оба примера достаточно отличаются реализацией. Пример не из документации подразумевает «более сильную» инкапсуляцию, так как извне ко внутреннему классу доступ получить нельзя, поэтому создание объекта внутреннего класса происходит в конструкторе основного класса -- в апельсине. С другой стороны, у примера из документации есть доступ извне ко внутреннему классу сока, но всё равно, только через основной класс апельсина, как и создать объект сока можно только через объект апельсина, то есть подчёркивается взаимодействие на уровне объектов.
\textbf{Особенности внутренних классов}:
\begin{itemize}
\item Внутренний объект не существует без внешнего. Это логично -- для этого \code{Juice} был создан внутренним классом, чтобы в программе не появлялись апельсиновые соки из воздуха.
\item Внутренний объект имеет доступ ко всему внешнему. Код внутреннего класса имеет доступ ко всем полям и методам экземпляра (и к статическим членам) окружающего класса, включая все члены, даже объявленные как \code{private}.
\item Внешний объект не имеет доступа ко внутреннему без создания объекта. Это логично, так как экземпляров внутреннего класса может быть создано сколь угодно много, и к какому именно из них обращаться?
\item У внутренних классов есть модификаторы доступа. Это влияет на то, где в программе возможно создавать экземпляры внутреннего класса. Единственное сохраняющееся требование — объект внешнего класса тоже обязательно должен существовать и быть видимым.
\item Внутренний класс не может называться как внешний, однако, это правило не распространяется ни на поля, ни на методы;
\item Во внутреннем классе нельзя иметь не-final статические поля. Статические поля, методы и классы являются конструкциями верхнего уровня, которые не связаны с конкретными объектами, в то время как каждый внутренний класс связан с экземпляром окружающего класса.
\item Объект внутреннего класса нельзя создать в статическом методе «внешнего» класса. Это объясняется особенностями устройства внутренних классов. У внутреннего класса могут быть конструкторы с параметрами или только конструктор по умолчанию. Но независимо от этого, когда создаётся объект внутреннего класса, в него неявно передаётся ссылка на объект внешнего класса.
\item Со внутренними классами работает наследование и полиморфизм.
\end{itemize}
\subsubsection{Задания для самопроверки}
\begin{enumerate}
\item Внутренний класс: 1
\begin{enumerate}
\item реализует композицию;
\item это служебный класс;
\item не требует объекта внешнего класса;
\end{enumerate}
\item Инкапсуляция с использованием внутренних классов: 2
\begin{enumerate}
\item остаётся неизменной
\item увеличивается
\item уменьшается
\end{enumerate}
\item Статические поля внутренних классов: 2
\begin{enumerate}
\item могут существовать
\item могут существовать только константными
\item не могут существовать
\end{enumerate}
\end{enumerate}
\subsubsection{Локальные классы}
Классы -- это новый тип данных для программы, поэтому технически возможно создавать классы, а также описывать их, например, внутри методов. Это довольно редко используется но синтаксически язык позволяет это сделать. \textbf{Локальные классы} — это подвид внутренних классов. Однако, у локальных классов есть ряд важных особенностей и отличий от внутренних классов. Главное заключается в их объявлении.
\begin{frm} \info Локальный класс объявляется только в блоке кода. Чаще всего — внутри какого-то метода внешнего класса.
\end{frm}
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Пример локального класса}]
public class Animal {
void performBehavior(boolean state) {
class Brain {
void sleep() {
if (state)
System.out.println("Sleeping");
else
System.out.println("Not sleeping");
}
}
Brain brain = new Brain();
brain.sleep();
}
}
\end{lstlisting}
Например, некоторое животное, у которого устанавливается состояние спит оно или нет. Метод \code{performBehavior()} принимает на вход булево значение и определяет, спит ли животное. Мог возникнуть вопрос: зачем? Итоговое решение об архитектуре проекта всегда зависит от структуры, сложности и предназначения программы.
\textbf{Особенности локальных классов}:
\begin{itemize}
\item Локальный класс сохраняет доступ ко всем полям и методам внешнего класса, а также ко всем константам, объявленным в текущем блоке кода, то есть полям и аргументам метода объявленным как \code{final}. Начиная с JDK 1.8 локальный класс может обращаться к любым полям и аргументам метода объявленным в текущем блоке кода, даже если они не объявлены как \code{final}, но только в том случае если их значение не изменяется после инициализации.
\item Локальный класс должен иметь свои внутренние копии всех локальных переменных, которые он использует (эти копии автоматически создаются компилятором). Единственный способ обеспечить идентичность значений локальной переменной и ее копии объявить локальную переменную как \code{final}.
\item Экземпляры локальных классов, как и экземпляры внутренних классов, имеют окружающий экземпляр, ссылка на который неявно передается всем конструкторам локальных классов. То есть, сперва должен быть создан экземпляр внешнего класса, а только затем экземпляр внутреннего класса.
\end{itemize}
\subsubsection{Статические вложенные классы}
При объявлении такого класса используется ключевое слово \code{static}. Для примера в классе котика % lst:cmpcat
и заменим метод \code{voice()} на статический класс.
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Статический вложенный класс}]
public class Cat {
private String name;
private String color;
private int age;
public Cat()
public Cat(String name, String color, int age) {
this.name = name;
this.color = color;
this.age = age;
}
static class Voice {
private final int volume;
public Voice(int volume) {
this.volume = volume;
}
public void sayMur() {
System.out.printf("A cat purrs with volume %d\n", volume);
}
}
}
\end{lstlisting}
То есть, такое мурчание котика может присутствовать без видимости и понимания, что именно за котик присутствует в данный момент. Также, добавлена возможность установить уровень громкости мурчанья.
\begin{frm} \info
Основное отличие статических и нестатических вложенных классов в том, что объект статического класса не хранит ссылку на конкретный экземпляр внешнего класса.
\end{frm}
Без объекта внешнего класса объект внутреннего просто не мог существовать. Для статических вложенных классов это не так. Объект статического вложенного класса может существовать сам по себе. В этом плане статические классы более независимы, чем нестатические. Довольно важный момент заключается в том, что при создании такого объекта нужно указывать название внешнего класса,
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Использование статического класса}]
Cat.Voice voice = new Cat.Voice(100);
voice.sayMur();
\end{lstlisting}
Статический вложенный класс может обращаться только к статическим полям внешнего класса. При этом неважно, какой модификатор доступа имеет статическая переменная во внешнем классе.
Не следует путать объекты с переменными. Если речь идёт о статических переменных — да, статическая переменная класса существует в единственном экземпляре. Но применительно ко вложенному классу \code{static} означает лишь то, что его объекты не содержат ссылок на объекты внешнего класса.
\subsubsection{Задания для самопроверки}
\begin{enumerate}
\item Вложенный класс: 1
\begin{enumerate}
\item реализует композицию;
\item это локальный класс;
\item всегда публичный;
\end{enumerate}
\item Статический вложенный классо бладает теми же свойствами, что: 2
\begin{enumerate}
\item константный метод
\item внутренний класс
\item статическое поле
\end{enumerate}
\end{enumerate}
\subsection{Исключения}
\subsubsection{Понятие}
Язык программирования -- это, в первую очередь, набор инструментов. Например, есть художник. У художника есть набор всевозможных красок, кистей, холстов, карандашей, мольберт, ластик и прочие. Это всё его инструменты. Тоже самое для программиста. У программиста есть язык программирования, который предоставляет ему инструменты: циклы, условия, классы, функции, методы, ООП, фрейморки, библиотеки. Исключения -- это один из инструментов. Исключения всегда следует рассматривать как ещё один инструмент для работы программиста.
\begin{frm} \info Исключение -- это отступление от общего правила, несоответствие обычному порядку вещей
\end{frm}
В общем случае, возникновение исключительной ситуации, это ошибка в программе, но основным вопросом является следующий. Возникшая ошибка -- это:
\begin{itemize}
\item ошибка в коде программы;
\item ошибка в действиях пользователя;
\item ошибка в аппаратной части компьютера?
\end{itemize}
\subsubsection{Общие сведения}
При возникновении ошибок создаётся объект класса «исключение», и в этот объект записывается какое-то максимальное количество информации о том, какая ошибка произошла, чтобы потом прочитать и понять, где проблема. Соответственно эти объекты возможно «ловить и обрабатывать».
\begin{figure}[H]
\fontsize{11}{1}\selectfont
\includesvg[scale=.85]{pics/jc-04-throwable.svg}
\caption{Часть иерархии исключений}
\label{pic:exception-hierarchy}
\end{figure}
Все исключения наследуются от класса \code{Throwable} и могут быть как обязательные к обработке, так и необязательные. Есть ещё подкласс \code{Error}, но он больше относится к аппаратным сбоям или серьёзным алгоритмическим или архитектурным ошибкам, и на данном этапе интереса не представляет, потому что поймав, например, \code{OutOfMemoryError} средствами Java прямо в программе с ним ничего сделать невозможно, такие ошибки необходимо обрабатывать и не допускать в процессе разработки ПО.
Для изучения и примеров, воспользуемся двумя подклассами \code{Throwable} -- \code{Exception} -- \code{RuntimeException} и \code{IOException}.
\begin{frm} \excl Все исключения (\textbf{checked}), кроме наследников \code{RuntimeException} (\textbf{unchecked}), необходимо обрабатывать.
\end{frm}
Опишем на простом примере, один метод вызывает другой, второй вызывает третий и последний всё портит:
\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 div1(int a, int b) {
return div0(a, b);
}
private static int div2(int a, int b) {
return div1(a, b);
}
\end{lstlisting}
\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}
\code{ArithmeticException} является наследником класса \code{RuntimeEcxeption} поэтому статический анализатор кода его не подчеркнул, и «ловить» его не обязательно.
При работе с исключениями часто можно встретить слова, похожие на сленг, но это не так. Чаще всего, то, что звучит как сленг -- просто перевод ключевых слов языка, осуществляющих то или иное действие.
\begin{itemize}
\item try -- (англ. пробовать) пробовать, пытаться;
\item catch -- (англ. ловить) ловить, поймать, хватать;
\item throw -- (англ. бросать) выбрасывать, бросать, кидать;
\item NullPointerException -- НПЕ, налпоинтер;
\item и другие...
\end{itemize}
Если посмотреть на метод \code{div0(int a, int b)} с точки зрения программирования, он написан очень хорошо -- алгоритм понятен, метод с единственной ответственностью, однако, из поставленной перед методом задачи очевидно, что он не может работать при всех возможных входных значениях. То есть если вторая переменная равна нулю, то это ошибка. Необходимо запретить пользователю передавать в качестве делителя ноль. Самое простое -- ничего не делать, но в программе на языке Java так нельзя, если мы объявили, что метод имеет возвращающее значение, он обязан что-то вернуть.
\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}
А что вернуть, неизвестно, ведь от метода ожидается результат деления. Поэтому, возможно руками сделать проверку \code{(b == 0f)} и «выбросить» пользователю так называемый \textbf{объект исключения} с текстом ошибки, объясняющим произошедшее, а иначе вернём \code{a / b}.
\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}
Следовательно, если делитель не равен нулю произойдёт обычное деление, а если равен -- будет «выброшено» исключение.
\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}
Очевидно, что ключевое слово \code{new} вызывает конструктор, нового объекта какого-то класса, в который передаётся какой-то параметр, в данном конкретном случае это строка с сообщением.
\subsubsection{Объект исключения}
Ключевое слово \code{throw} заставляет созданный объект исключения начать свой путь по родительским методам, пока этот объект не встретится с каким-то обработчиком. В данном конкретном случае -- это обработчик виртуальной машины (по-умолчанию), который в специальный поток error выводит так называемый stacktrace, и завершает дальнейшее выполнение метода (технически, всего потока целиком).
\begin{figure}[H]
\fontsize{12}{1}\selectfont
\includesvg[scale=1.01]{pics/jc-04-threading.svg}
\caption{Принципиальная схема работы приложения}
\label{pic:throw-treading}
\end{figure}
Все программы в Java всегда многопоточны. На старте программы запускаются так называемые потоки, которые работают псевдопараллельно и предназначены каждый для решения своих собственных задач, например, это основной поток, поток сборки мусора, поток обработчика ошибок, потоки графического интерфейса. Основная задача этих потоков -- делать своё дело и иногда обмениваться информацией.
В \textbf{stacktrace}, содержащийся в объекте исключения, кладётся максимальное количество информации о типе исключения, его сообщении, иерархии методов, вызовы которых привели к исключительной ситуации.
\begin{frm} \info Важно научиться читать stacktrace на как можно более раннем этапе изучения программирования.
\end{frm}
Итак стектрейс. В стектрейсе на рис. \hrf{pic:result-except-div-better} видно, что исключение было создано в потоке main, и является объектом класса \code{RuntimeException}, сообщение также было предусмотрительно приложено автором кода. Важно понять, что исключение -- это объект класса. Далее, можно просто читать последовательно строку за строкой -- в каком методе создался этот объект, на какой строке, в каком классе. Далее видно, какой код вызвал этот метод, на какой строке, в каком классе.
Если не написать явного выбрасывания никакого исключения, оно всё равно будет выброшено. Это общее поведение исключения. Оно где-то случается, прекращает выполнение текущего метода, и начинает лететь по стеку вызовов вверх. Возможно даже долетит до обработчика по-умолчанию. Некоторые исключения создаются в коде явно, некоторые самой Java, они вполне стандартные, например выход за пределы массива, деление на ноль, и классический \code{NullPointer}.
Создадим экземпляр класса исключения внутри метода, вызываемого из \code{main}:
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Инициализация объекта исключения},label={lst:except-init}]
RuntimeException e = new RuntimeException();
\end{lstlisting}
Если оставить программу в таком виде и запустить, то ничего не произойдёт, исключение нужно выкинуть (активировать, возбудить, сгенерировать). Для этого есть ключевое слово
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Выбрасывание объекта исключения},label={lst:except-throw}]
throw e;
\end{lstlisting}
Компилятор ошибок не обнаружил и всё пропустил, а интерпретатор наткнулся на класс исключения, и написал в консоль, что в основном потоке программы возникло исключение в пакете в классе на такой-то строке. По стэктрейсу возможно проследить что откуда вызвалось и как программа дошла до исключительной ситуации. Возможно также наследоваться от какого-то исключения и создать свой класс исключений.
\begin{frm} \info Исключения, наследники \code{RuntimeException}, являются \textbf{Unchecked}, то есть не обязательные для обработки на этапе написания кода. \textit{Все остальные} \code{Throwable} -- обязательные для обработки, статический анализатор кода не просто их выделяет, а обязывает их обрабатывать на этапе написания кода. И просто не скомпилирует проект если в коде есть необработанные исключения, также известные как \textbf{Checked}.
\end{frm}
\subsubsection{Обработка}
\begin{frm} \excl Первое, и самое важное, что нужно понять -- почему что-то пошло (или пойдёт) «не так», поэтому не пытайтесь что-то ловить, пока не поймёте что именно произошло, от этого понимания будет зависеть \textit{способ} ловли.
\end{frm}
Исключение ловится двухсекционным оператором \textbf{\code{try...catch}}, а именно, его первой секцией \code{try}. Это секция, в которой предполагается возникновение исключения, и предполагается, что его возможно обработать. А в секции \code{catch} пишется имя класса исключения, которое будет поймано ловим, и имя объекта (идентификатор), через который внутри секции можно к пойманному объекту обращаться. Секция \code{catch} ловит указанное исключение и \textit{всех его наследников}.
\begin{frm} \info Рекомендуется писать максимально узко направленные секции \code{catch}, потому что надо стараться досконально знать как работает программа, и какие исключения она может выбрасывать. Также, потому что разные исключения могут по-разному обрабатываться.
\end{frm}
Секций \code{catch} может быть любое количество. Как только объект исключения обработан, он уничтожается и в следующие \code{catch} не попадает. Однако, объект возможно явно отправить на обработчик «выше», ключевым словом \code{throw} (чаще всего, используется \code{RuntimeException} с конструктором копирования).
Когда какой-то метод выбрасывает исключение у разработчика есть два основных пути:
\begin{itemize}
\item обязанность вынести объявление этого исключения в сигнатуру метода, что будет говорить тем, кто его вызывает о том, что в методе может возникнуть исключение;
\item исключение необходимо непосредственно в методе обработать, иначе ничего не скомпилируется.
\end{itemize}
В случае, если объявление исключения выносится в сигнатуру, вызывающий метод должен обработать это исключение точно таким-же образом -- либо в вызове, либо вынести в сигнатуру. Исключением из этого правила является класс \code{RuntimeException}. Все его наследники, включая его самого, обрабатывать не обязательно. Обычно, уже по названию понятно что случилось, и, помимо говорящих названий, там содержится много информации, например, номер строки, вызвавшей исключительную ситуацию.
\begin{frm} \info Общее правило работы с исключениями одно -- если исключение штатное -- его надо сразу обработать, если нет -- надо дождаться, пока программа упадёт.
\end{frm}
Общий вид оператора try...catch можно описать следующим образом:
\begin{verbatim}
try {
метод, выбрасывающий исключение
} catch (имя класса исключения и идентификатор) {
команды, обрабатывающие исключение
}
\end{verbatim}
Если произошло исключение, объект исключения попадает в \code{catch}, и управление ходом выполнения программы попадает в эту секцию. Чаще всего, здесь содержится код, помогающей программе не завершиться. Очень часто в процессе разработки нужно сделать так, чтобы в процессе выполнения что-то конкретное об исключении выводилось на экран, для этого у экземпляра есть метод \code{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}
\textbf{Второй вариант обработки исключений} -- в сигнатуре метода пишется
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Обработка исключений в сигнатуре},label={lst:except-throws}]
throws IOException,
\end{lstlisting}
и, через запятую, все остальные возможные исключения этого метода. После этого, с ним не будет проблем исполнения, но у метода который его вызовет -- появилась необходимость обработать все 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}
То есть, способ работы с объектом данного класса (полностью без ошибок и других нештатных ситуаций) будет иметь следующий вид
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Работа в штатном режиме},label={lst:test-stream-main}]
TestStream stream = new TestStream();
int a = stream.read()
stream.close()
\end{lstlisting}
Для примера, внутри метода чтения создаётся \code{FileInputStream} который может генерировать обязательный к проверке на этапе написания кода \code{FileNotFoundException}, который является наследником \code{IOException}, который, в свою очередь, наследуется от \code{Exception}.
Возникает два варианта: либо обернуть в \code{try...catch}, либо совершенно непонятно, как должна обрабатываться данная исключительная ситуация, и обработать её должна сторона, которая вызывает метод чтения, в таком случае пишется, что метод может выбрасывать исключения. И тогда \code{TestStream} компилируется без проблем, а вот \code{main} скомпилироваться уже не может. В нём нужно оборачивать в \code{try...catch}.
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Метод чтения}]
int read() {
FileInputStream s = new FileInputStream("file.txt");
System.out.println("read");
return 1;
}
}
\end{lstlisting}
\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}
\begin{frm} \excl Важный момент. Задачи бывают разные. Исключения -- это инструмент, который нетривиально работает. Важно при написании кода понять, возникающая исключительная ситуация -- штатная, или нештатная. В большинстве случаев -- ситуации нештатные, поэтому надо «уронить» приложение и разбираться с тем, что именно произошло. Допустим, для вашего приложения обязательно какой-то файл должен быть, без него дальше нет смысла продолжать. Что делать, если его нет? Ситуация явно нештатная. Самое плохое, что можно сделать -- ничего не делать. Это самое страшное, когда программа повела себя как-то не так, а ни мы, разработчики, ни пользователь об этом даже не узнали. Допустим, мы хотим прочитать файл, вывести в консоль, но мы в обработчике исключения просто выводим стектрейс куда-то, какому-то разработчику в среду разработки, и наши действительно важные действия не выполнились. Надо завершать работу приложения. Как завершать? \code{throw new RuntimeException(e)}. Крайне редко случаются ситуации, когда у исключения достаточно распечатать стектрейс.
\end{frm}
Потоки ввода-вывода всегда нужно закрывать. Предположим, что в тестовом потоке открылся файл, из него что-то прочитано, потом метод завершился с исключением, а файл остался незакрытым, ресурсы заняты. Дописав класс \code{TestStream} при работе с ним, возвращаем из \code{read} единицу и логируем, что всё прочитали в \code{main}.
\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}
Далее представим, что в методе \code{read} что-то пошло не так, выбрасываем исключение, и видим в консоли, что поток создан, произошло исключение, конец программы. Очевидно, поток не закрылся. Что делать?
Делать секцию \code{finally}. Секция \code{finally} будет выполнена в любом случае, не важно, будет ли поймано секциями \code{catch} какое-то исключение, или нет. Возникает небольшая проблема видимости, объявление идентификатора тестового потока необходимо вынести за пределы секции \code{try}.
Теперь немного неприятностей. Написанный блок \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}
\item напишите два наследника класса Exception: ошибка преобразования строки и ошибка преобразования столбца
\item разработайте исключения-наследники так, чтобы они информировали пользователя в формате ожидание/реальность
\item для проверки напишите программу, преобразующую квадратный массив целых чисел 5х5 в сумму чисел в этом массиве, при этом, программа должна выбросить исключение, если строк или столбцов в исходном массиве окажется не 5.
\end{enumerate}
\newpage
\printnomenclature[40mm]
\end{document}

View File

@ -26,9 +26,9 @@
showgrid="true"
showborder="false"
borderlayer="false"
inkscape:zoom="8.6634554"
inkscape:cx="594.39332"
inkscape:cy="469.78945"
inkscape:zoom="1.9531432"
inkscape:cx="431.86797"
inkscape:cy="488.95543"
inkscape:window-width="1511"
inkscape:window-height="832"
inkscape:window-x="0"
@ -111,12 +111,12 @@
id="layer1">
<text
xml:space="preserve"
style="font-size:4.93888889px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-opacity:1;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;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-opacity:1"
x="60.956562"
y="96.191261"
id="text790"><tspan
sodipodi:role="line"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.265;stroke-opacity:1;-inkscape-font-specification:'IBM Plex Sans';font-family:'IBM Plex Sans';font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;font-size:4.93888889px"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;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.265;stroke-opacity:1"
x="60.956562"
y="96.191261"
id="tspan11908">java class file</tspan></text>
@ -133,155 +133,155 @@
y="124.11515" /></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93889px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-opacity:1"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;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-opacity:1"
x="111.84619"
y="96.395851"
id="text848"><tspan
sodipodi:role="line"
id="tspan846"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93889px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';stroke-width:0.265"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';stroke-width:0.265"
x="111.84619"
y="96.395851">class loader</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93889px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-opacity:1"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333333px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-opacity:1"
x="66"
y="124"
id="text2304"><tspan
sodipodi:role="line"
id="tspan2302"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93889px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';stroke-width:0.265"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';stroke-width:0.265;font-size:4.23333333px"
x="66"
y="124">method area</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93889px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-opacity:1"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333333px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-opacity:1"
x="102.36334"
y="123.94704"
id="text3034"><tspan
sodipodi:role="line"
id="tspan3032"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93889px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';stroke-width:0.265"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';stroke-width:0.265;font-size:4.23333333px"
x="102.36334"
y="123.94704">heap</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93889px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-opacity:1"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333333px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-opacity:1"
x="126.9079"
y="123.80221"
id="text3038"><tspan
sodipodi:role="line"
id="tspan3036"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93889px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';stroke-width:0.265"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';stroke-width:0.265;font-size:4.23333333px"
x="126.9079"
y="123.80221">stack</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93889px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-opacity:1"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333333px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-opacity:1"
x="152"
y="124"
id="text3768"><tspan
sodipodi:role="line"
id="tspan3766"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93889px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';stroke-width:0.265"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';stroke-width:0.265;font-size:4.23333333px"
x="152"
y="124">java threads</tspan></text>
<text
xml:space="preserve"
style="font-size:4.93888889px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-opacity:1;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal"
style="font-size:4.23333333px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-opacity:1;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal"
x="122.48949"
y="133.47887"
id="text4498"><tspan
sodipodi:role="line"
style="stroke-width:0.265;-inkscape-font-specification:'IBM Plex Sans';font-family:'IBM Plex Sans';font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;font-size:4.93888889px"
style="stroke-width:0.265;-inkscape-font-specification:'IBM Plex Sans';font-family:'IBM Plex Sans';font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;font-size:4.23333333px"
x="122.48949"
y="133.47887"
id="tspan4500">program counter registers</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93889px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-opacity:1"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333333px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-opacity:1"
x="66"
y="134"
id="text5230"><tspan
sodipodi:role="line"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93889px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';stroke-width:0.265"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';stroke-width:0.265;font-size:4.23333333px"
x="66"
y="134"
id="tspan5232">native internal threads</tspan></text>
<text
xml:space="preserve"
style="font-size:4.93888889px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-opacity:1;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal"
style="font-size:4.23333333px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-opacity:1;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal"
x="73.237595"
y="155.814"
id="text5962"><tspan
sodipodi:role="line"
id="tspan5960"
style="stroke-width:0.265;-inkscape-font-specification:'IBM Plex Sans';font-family:'IBM Plex Sans';font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;font-size:4.93888889px"
style="stroke-width:0.265;-inkscape-font-specification:'IBM Plex Sans';font-family:'IBM Plex Sans';font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;font-size:4.23333333px"
x="73.237595"
y="155.814">execution engine</tspan></text>
<text
xml:space="preserve"
style="font-size:4.93888889px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-opacity:1;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal"
style="font-size:4.23333333px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-opacity:1;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal"
x="57.221085"
y="163.8349"
id="text6329"><tspan
sodipodi:role="line"
id="tspan6327"
style="stroke-width:0.265;-inkscape-font-specification:'IBM Plex Sans';font-family:'IBM Plex Sans';font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;font-size:4.93888889px"
style="stroke-width:0.265;-inkscape-font-specification:'IBM Plex Sans';font-family:'IBM Plex Sans';font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;font-size:4.23333333px"
x="57.221085"
y="163.8349">JIT compiler</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93889px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-opacity:1"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333333px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-opacity:1"
x="91"
y="164"
id="text7422"><tspan
sodipodi:role="line"
id="tspan7420"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93889px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';stroke-width:0.265"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';stroke-width:0.265;font-size:4.23333333px"
x="91"
y="164">garbage collector</tspan></text>
<text
xml:space="preserve"
style="font-size:4.93888889px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-opacity:1;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal"
style="font-size:4.23333333px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-opacity:1;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal"
x="141.01183"
y="157.82979"
id="text8152"><tspan
sodipodi:role="line"
id="tspan8150"
style="stroke-width:0.265;-inkscape-font-specification:'IBM Plex Sans';font-family:'IBM Plex Sans';font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;font-size:4.93888889px"
style="stroke-width:0.265;-inkscape-font-specification:'IBM Plex Sans';font-family:'IBM Plex Sans';font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;font-size:4.23333333px"
x="141.01183"
y="157.82979">native method</tspan><tspan
sodipodi:role="line"
style="stroke-width:0.265;-inkscape-font-specification:'IBM Plex Sans';font-family:'IBM Plex Sans';font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;font-size:4.93888889px"
style="stroke-width:0.265;-inkscape-font-specification:'IBM Plex Sans';font-family:'IBM Plex Sans';font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;font-size:4.23333333px"
x="141.01183"
y="164.00342"
id="tspan8154">interface</tspan></text>
<text
xml:space="preserve"
style="font-size:4.93888889px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-opacity:1;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal"
style="font-size:4.23333333px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-opacity:1;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal"
x="181.05193"
y="157.77907"
id="text8884"><tspan
sodipodi:role="line"
id="tspan8882"
style="stroke-width:0.265;-inkscape-font-specification:'IBM Plex Sans';font-family:'IBM Plex Sans';font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;font-size:4.93888889px"
style="stroke-width:0.265;-inkscape-font-specification:'IBM Plex Sans';font-family:'IBM Plex Sans';font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;font-size:4.23333333px"
x="181.05193"
y="157.77907">native method</tspan><tspan
sodipodi:role="line"
style="stroke-width:0.265;-inkscape-font-specification:'IBM Plex Sans';font-family:'IBM Plex Sans';font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;font-size:4.93888889px"
style="stroke-width:0.265;-inkscape-font-specification:'IBM Plex Sans';font-family:'IBM Plex Sans';font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;font-size:4.23333333px"
x="181.05193"
y="163.9527"
id="tspan8886">library</tspan></text>
<text
xml:space="preserve"
style="font-size:4.93888889px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-opacity:1;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal"
style="font-size:4.23333333px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-opacity:1;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal"
x="103.22704"
y="115.05011"
id="text10342"><tspan
sodipodi:role="line"
id="tspan10340"
style="stroke-width:0.265;-inkscape-font-specification:'IBM Plex Sans';font-family:'IBM Plex Sans';font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;font-size:4.93888889px"
style="stroke-width:0.265;-inkscape-font-specification:'IBM Plex Sans';font-family:'IBM Plex Sans';font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;font-size:4.23333333px"
x="103.22704"
y="115.05011">runtime data area</tspan></text>
<text
@ -368,8 +368,8 @@
<rect
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-opacity:1"
id="rect13444"
width="49.896049"
height="4.9799647"
width="50.938873"
height="5.0722198"
x="65.061127"
y="129.92778" />
<rect

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -7,7 +7,7 @@
viewBox="0 0 210 297"
version="1.1"
id="svg5"
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
inkscape:version="1.2.1 (9c6d41e4, 2022-07-14)"
sodipodi:docname="jc-03-class-obj-fields.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
@ -17,8 +17,8 @@
id="namedview7"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
borderopacity="0.25"
inkscape:showpageshadow="false"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#ffffff"
@ -26,14 +26,15 @@
showgrid="true"
showborder="false"
inkscape:zoom="4"
inkscape:cx="174.5"
inkscape:cy="366.875"
inkscape:window-width="2560"
inkscape:window-height="1387"
inkscape:window-x="-8"
inkscape:window-y="22"
inkscape:window-maximized="1"
inkscape:current-layer="layer1">
inkscape:cx="169.5"
inkscape:cy="336.875"
inkscape:window-width="1534"
inkscape:window-height="837"
inkscape:window-x="0"
inkscape:window-y="25"
inkscape:window-maximized="0"
inkscape:current-layer="layer1"
borderlayer="false">
<inkscape:grid
type="xygrid"
id="grid1775" />
@ -85,24 +86,24 @@
id="layer1">
<text
xml:space="preserve"
style="font-size:4.9389px;line-height:1.25;font-family:'PT Astra Serif';-inkscape-font-specification:'PT Astra Serif';stroke-width:0.264583"
style="font-size:4.9389px;line-height:1.25;font-family:'PT Astra Serif';-inkscape-font-specification:'PT Astra Serif';stroke-width:0.264583;stroke:none;stroke-opacity:1;fill:#000000;fill-opacity:1"
x="34.229366"
y="78.023079"
id="text2194"><tspan
sodipodi:role="line"
id="tspan2192"
style="stroke-width:0.264583"
style="stroke-width:0.264583;stroke:none;stroke-opacity:1;fill:#000000;fill-opacity:1"
x="34.229366"
y="78.023079">class</tspan></text>
<text
xml:space="preserve"
style="font-size:4.9389px;line-height:1.25;font-family:'PT Astra Serif';-inkscape-font-specification:'PT Astra Serif';stroke-width:0.264583"
style="font-size:4.9389px;line-height:1.25;font-family:'PT Astra Serif';-inkscape-font-specification:'PT Astra Serif';stroke-width:0.264583;fill:#000000;fill-opacity:1"
x="21.193127"
y="86.016037"
id="text2248"><tspan
sodipodi:role="line"
id="tspan2246"
style="stroke-width:0.264583"
style="stroke-width:0.264583;fill:#000000;fill-opacity:1"
x="21.193127"
y="86.016037">fields</tspan></text>
<rect

Before

Width:  |  Height:  |  Size: 7.3 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

View File

@ -7,7 +7,7 @@
viewBox="0 0 210 297"
version="1.1"
id="svg5"
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
inkscape:version="1.2.1 (9c6d41e4, 2022-07-14)"
sodipodi:docname="jc-03-class-obj-full.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
@ -18,7 +18,7 @@
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:showpageshadow="false"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#ffffff"
@ -27,13 +27,14 @@
showborder="false"
inkscape:zoom="4"
inkscape:cx="174.5"
inkscape:cy="366.875"
inkscape:window-width="2560"
inkscape:window-height="1387"
inkscape:window-x="-8"
inkscape:window-y="22"
inkscape:window-maximized="1"
inkscape:current-layer="layer1">
inkscape:cy="367"
inkscape:window-width="1534"
inkscape:window-height="456"
inkscape:window-x="0"
inkscape:window-y="25"
inkscape:window-maximized="0"
inkscape:current-layer="layer1"
borderlayer="false">
<inkscape:grid
type="xygrid"
id="grid1775" />

Before

Width:  |  Height:  |  Size: 8.9 KiB

After

Width:  |  Height:  |  Size: 8.9 KiB

View File

@ -7,7 +7,7 @@
viewBox="0 0 210 297"
version="1.1"
id="svg5"
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
inkscape:version="1.2.1 (9c6d41e4, 2022-07-14)"
sodipodi:docname="jc-03-class-obj-nostatic.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
@ -18,7 +18,7 @@
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:showpageshadow="false"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#ffffff"
@ -27,13 +27,14 @@
showborder="false"
inkscape:zoom="4"
inkscape:cx="174.5"
inkscape:cy="366.875"
inkscape:window-width="2560"
inkscape:window-height="1387"
inkscape:window-x="-8"
inkscape:window-y="22"
inkscape:window-maximized="1"
inkscape:current-layer="layer1">
inkscape:cy="367"
inkscape:window-width="1534"
inkscape:window-height="456"
inkscape:window-x="0"
inkscape:window-y="25"
inkscape:window-maximized="0"
inkscape:current-layer="layer1"
borderlayer="false">
<inkscape:grid
type="xygrid"
id="grid1775" />

Before

Width:  |  Height:  |  Size: 7.7 KiB

After

Width:  |  Height:  |  Size: 7.7 KiB

BIN
pics/jc-03-finalclass.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

103
pics/jc-03-modifiers.svg Normal file
View File

@ -0,0 +1,103 @@
<?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-03-modifiers.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"
showguides="true"
inkscape:zoom="15.985772"
inkscape:cx="308.14903"
inkscape:cy="419.154"
inkscape:window-width="1534"
inkscape:window-height="929"
inkscape:window-x="0"
inkscape:window-y="25"
inkscape:window-maximized="0"
inkscape:current-layer="layer1">
<inkscape:grid
type="xygrid"
id="grid132" />
<sodipodi:guide
position="80.697915,197.78126"
orientation="1,0"
id="guide1128"
inkscape:locked="false" />
</sodipodi:namedview>
<defs
id="defs2" />
<g
inkscape:label="Слой 1"
inkscape:groupmode="layer"
id="layer1">
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;stroke-width:0.765"
x="74.083336"
y="117.73959"
id="text250"><tspan
sodipodi:role="line"
id="tspan248"
style="stroke-width:0.765"
x="74.083336"
y="117.73959">public</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;stroke-width:0.765"
x="72.760414"
y="104.51041"
id="text416"><tspan
sodipodi:role="line"
id="tspan414"
style="stroke-width:0.765"
x="72.760414"
y="104.51041">default</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;stroke-width:0.765"
x="72.760414"
y="97.895836"
id="text420"><tspan
sodipodi:role="line"
id="tspan418"
style="stroke-width:0.765"
x="72.760414"
y="97.895836">private</tspan></text>
<path
style="fill:none;stroke:#000000;stroke-width:0.265;stroke-dasharray:none;stroke-opacity:1"
d="M 80.697917,83.34375 55.5625,119.0625 h 50.27083 L 80.697917,83.34375"
id="path476"
sodipodi:nodetypes="cccc" />
<path
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-dasharray:none;stroke-opacity:1;stroke-linecap:square"
d="m 68.791666,100.54167 h 23.8125"
id="path1130" />
<path
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-dasharray:none;stroke-opacity:1"
d="M 64.822916,105.83333 H 96.572915"
id="path1132" />
<path
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-dasharray:none;stroke-opacity:1;stroke-linecap:square"
d="M 59.531249,113.77083 H 101.86458"
id="path1134" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

@ -0,0 +1,114 @@
<?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"
sodipodi:docname="jc-04-modifiers-full.svg"
inkscape:version="1.2.1 (9c6d41e4, 2022-07-14)"
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"
showguides="true"
inkscape:zoom="15.985772"
inkscape:cx="308.14903"
inkscape:cy="419.154"
inkscape:window-width="1534"
inkscape:window-height="929"
inkscape:window-x="0"
inkscape:window-y="25"
inkscape:window-maximized="0"
inkscape:current-layer="layer1">
<inkscape:grid
type="xygrid"
id="grid132" />
<sodipodi:guide
position="80.697915,197.78126"
orientation="1,0"
id="guide1128"
inkscape:locked="false" />
</sodipodi:namedview>
<defs
id="defs2" />
<g
inkscape:label="Слой 1"
inkscape:groupmode="layer"
id="layer1">
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;stroke-width:0.765"
x="74.083336"
y="117.73959"
id="text250"><tspan
sodipodi:role="line"
id="tspan248"
style="stroke-width:0.765"
x="74.083336"
y="117.73959">public</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;stroke-width:0.765"
x="70.114586"
y="111.125"
id="text304"><tspan
sodipodi:role="line"
id="tspan302"
style="stroke-width:0.765"
x="70.114586"
y="111.125">protected</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;stroke-width:0.765"
x="72.760414"
y="104.51041"
id="text416"><tspan
sodipodi:role="line"
id="tspan414"
style="stroke-width:0.765"
x="72.760414"
y="104.51041">default</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;stroke-width:0.765"
x="72.760414"
y="97.895836"
id="text420"><tspan
sodipodi:role="line"
id="tspan418"
style="stroke-width:0.765"
x="72.760414"
y="97.895836">private</tspan></text>
<path
style="fill:none;stroke:#000000;stroke-width:0.265;stroke-dasharray:none;stroke-opacity:1"
d="M 80.697917,83.34375 55.5625,119.0625 h 50.27083 L 80.697917,83.34375"
id="path476"
sodipodi:nodetypes="cccc" />
<path
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-dasharray:none;stroke-opacity:1;stroke-linecap:square"
d="m 68.791666,100.54167 h 23.8125"
id="path1130" />
<path
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-dasharray:none;stroke-opacity:1"
d="M 64.822916,105.83333 H 96.572915"
id="path1132" />
<path
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-dasharray:none;stroke-opacity:1;stroke-linecap:square"
d="M 59.531249,113.77083 H 101.86458"
id="path1134" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.1 KiB

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

595
pics/jc-04-throwable.svg Normal file
View File

@ -0,0 +1,595 @@
<?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="svg2322"
inkscape:version="1.2.1 (9c6d41e4, 2022-07-14)"
sodipodi:docname="jc-04-throwable.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="namedview2324"
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="2.0877419"
inkscape:cx="305.59334"
inkscape:cy="296.2531"
inkscape:window-width="1529"
inkscape:window-height="935"
inkscape:window-x="151"
inkscape:window-y="25"
inkscape:window-maximized="0"
inkscape:current-layer="layer1">
<inkscape:grid
type="xygrid"
id="grid4258" />
</sodipodi:namedview>
<defs
id="defs2319" />
<g
inkscape:label="Слой 1"
inkscape:groupmode="layer"
id="layer1">
<text
xml:space="preserve"
style="font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;stroke-width:0.264999;stroke-linecap:square"
x="84.666664"
y="15.875"
id="text4625"><tspan
sodipodi:role="line"
id="tspan4623"
style="stroke-width:0.265"
x="84.666664"
y="15.875">Throwable</tspan></text>
<text
xml:space="preserve"
style="font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;stroke-width:0.264999;stroke-linecap:square"
x="11.906249"
y="35.71875"
id="text4629"><tspan
sodipodi:role="line"
id="tspan4627"
style="stroke-width:0.265"
x="11.906249"
y="35.71875">Error</tspan></text>
<text
xml:space="preserve"
style="font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;stroke-width:0.264999;stroke-linecap:square"
x="3.9687486"
y="46.302082"
id="text4633"><tspan
sodipodi:role="line"
id="tspan4631"
style="stroke-width:0.265"
x="3.9687486"
y="46.302082">подклассы</tspan><tspan
sodipodi:role="line"
style="stroke-width:0.265"
x="3.9687486"
y="52.475708"
id="tspan4635">Error</tspan></text>
<text
xml:space="preserve"
style="font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;stroke-width:0.264999;stroke-linecap:square"
x="105.83335"
y="25.135418"
id="text4639"><tspan
sodipodi:role="line"
id="tspan4637"
style="stroke-width:0.265"
x="105.83335"
y="25.135418">Exception</tspan></text>
<text
xml:space="preserve"
style="font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;stroke-width:0.264999;stroke-linecap:square"
x="63.5"
y="105.83334"
id="text5369"><tspan
sodipodi:role="line"
id="tspan5367"
style="stroke-width:0.265"
x="63.5"
y="105.83334">другие</tspan><tspan
sodipodi:role="line"
style="stroke-width:0.265"
x="63.5"
y="112.00696"
id="tspan5371">подклассы</tspan><tspan
sodipodi:role="line"
style="stroke-width:0.265"
x="63.5"
y="118.18058"
id="tspan5373">Exception</tspan></text>
<text
xml:space="preserve"
style="font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;stroke-width:0.264999;stroke-linecap:square"
x="59.53125"
y="31.75"
id="text5377"><tspan
sodipodi:role="line"
id="tspan5375"
style="stroke-width:0.265"
x="59.53125"
y="31.75">IOException</tspan></text>
<text
xml:space="preserve"
style="font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;stroke-width:0.264999;stroke-linecap:square"
x="43.65625"
y="42.333332"
id="text5381"><tspan
sodipodi:role="line"
id="tspan5379"
style="stroke-width:0.265"
x="43.65625"
y="42.333332">ClassNotFoundException</tspan></text>
<text
xml:space="preserve"
style="font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;stroke-width:0.264999;stroke-linecap:square"
x="43.65625"
y="52.916668"
id="text5385"><tspan
sodipodi:role="line"
id="tspan5383"
style="stroke-width:0.265"
x="43.65625"
y="52.916668">CloneNotSupportedException</tspan></text>
<text
xml:space="preserve"
style="font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;stroke-width:0.264999;stroke-linecap:square"
x="43.65625"
y="63.5"
id="text5389"><tspan
sodipodi:role="line"
id="tspan5387"
style="stroke-width:0.265"
x="43.65625"
y="63.5">EOFException</tspan></text>
<text
xml:space="preserve"
style="font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;stroke-width:0.264999;stroke-linecap:square"
x="43.65625"
y="74.083336"
id="text5393"><tspan
sodipodi:role="line"
id="tspan5391"
style="stroke-width:0.265"
x="43.65625"
y="74.083336">FileNotFoundException</tspan></text>
<text
xml:space="preserve"
style="font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;stroke-width:0.264999;stroke-linecap:square"
x="43.65625"
y="84.666664"
id="text5397"><tspan
sodipodi:role="line"
id="tspan5395"
style="stroke-width:0.265"
x="43.65625"
y="84.666664">MalformedURLException</tspan></text>
<text
xml:space="preserve"
style="font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;stroke-width:0.264999;stroke-linecap:square"
x="43.65625"
y="95.25"
id="text5401"><tspan
sodipodi:role="line"
id="tspan5399"
style="stroke-width:0.265"
x="43.65625"
y="95.25">UnknownHostException</tspan></text>
<text
xml:space="preserve"
style="font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;stroke-width:0.264999;stroke-linecap:square"
x="148.16667"
y="31.75"
id="text5405"><tspan
sodipodi:role="line"
id="tspan5403"
style="stroke-width:0.265"
x="148.16667"
y="31.75">RuntimeException</tspan></text>
<text
xml:space="preserve"
style="font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;stroke-width:0.264999;stroke-linecap:square"
x="142.87498"
y="42.333332"
id="text5409"><tspan
sodipodi:role="line"
id="tspan5407"
style="stroke-width:0.265"
x="142.87498"
y="42.333332">NullPointerException</tspan></text>
<text
xml:space="preserve"
style="font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;stroke-width:0.264999;stroke-linecap:square"
x="126.99999"
y="52.916668"
id="text5413"><tspan
sodipodi:role="line"
id="tspan5411"
style="stroke-width:0.265"
x="126.99999"
y="52.916668">IndexOutOfBoundsException</tspan></text>
<text
xml:space="preserve"
style="font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;stroke-width:0.264999;stroke-linecap:square"
x="128.32292"
y="63.5"
id="text5417"><tspan
sodipodi:role="line"
id="tspan5415"
style="stroke-width:0.265"
x="128.32292"
y="63.5">ArrayIndexOutOfBoundException</tspan></text>
<text
xml:space="preserve"
style="font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;stroke-width:0.264999;stroke-linecap:square"
x="132.29166"
y="74.083336"
id="text5421"><tspan
sodipodi:role="line"
id="tspan5419"
style="stroke-width:0.265"
x="132.29166"
y="74.083336">IllegalArgumentException</tspan></text>
<text
xml:space="preserve"
style="font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;stroke-width:0.264999;stroke-linecap:square"
x="145.52081"
y="84.666664"
id="text5425"><tspan
sodipodi:role="line"
id="tspan5423"
style="stroke-width:0.265"
x="145.52081"
y="84.666664">NumberFormatException</tspan></text>
<text
xml:space="preserve"
style="font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;stroke-width:0.264999;stroke-linecap:square"
x="142.87498"
y="105.83334"
id="text5429"><tspan
sodipodi:role="line"
id="tspan5427"
style="stroke-width:0.265"
x="142.87498"
y="105.83334">ClassCastException</tspan></text>
<text
xml:space="preserve"
style="font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;stroke-width:0.264999;stroke-linecap:square"
x="142.87498"
y="95.25"
id="text5433"><tspan
sodipodi:role="line"
id="tspan5431"
style="stroke-width:0.265"
x="142.87498"
y="95.25">ArithmeticException</tspan></text>
<text
xml:space="preserve"
style="font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;stroke-width:0.264999;stroke-linecap:square"
x="157.42709"
y="116.41668"
id="text5437"><tspan
sodipodi:role="line"
id="tspan5435"
style="stroke-width:0.265"
x="157.42709"
y="116.41668">другие </tspan><tspan
sodipodi:role="line"
style="stroke-width:0.265"
x="157.42709"
y="122.5903"
id="tspan5439">подклассы</tspan><tspan
sodipodi:role="line"
style="stroke-width:0.265"
x="157.42709"
y="128.76393"
id="tspan5441">RuntimeException</tspan></text>
<rect
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
id="rect5495"
width="17.197916"
height="6.6145835"
x="9.260417"
y="30.427084" />
<rect
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
id="rect5497"
width="29.104166"
height="11.90625"
x="2.6458328"
y="42.333332" />
<rect
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
id="rect5499"
width="26.458332"
height="6.614583"
x="83.34375"
y="10.583333" />
<rect
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
id="rect5501"
width="25.135416"
height="6.614583"
x="104.51041"
y="19.84375" />
<rect
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
id="rect5503"
width="30.427082"
height="6.614583"
x="58.208332"
y="26.458332" />
<rect
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
id="rect5505"
width="59.53125"
height="6.614583"
x="42.333332"
y="37.041668" />
<rect
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
id="rect5507"
width="70.114586"
height="6.614583"
x="42.333332"
y="47.625" />
<rect
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
id="rect5509"
width="34.395832"
height="6.614583"
x="42.333332"
y="58.208332" />
<rect
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
id="rect5511"
width="55.5625"
height="6.614583"
x="42.333332"
y="68.791664" />
<rect
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
id="rect5513"
width="59.53125"
height="6.614583"
x="42.333332"
y="79.375" />
<rect
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
id="rect5515"
width="58.208332"
height="6.614583"
x="42.333332"
y="89.958336" />
<rect
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
id="rect5517"
width="30.427084"
height="18.520838"
x="62.177082"
y="101.86458" />
<rect
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
id="rect5519"
width="44.979168"
height="6.614583"
x="146.84375"
y="26.458332" />
<rect
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
id="rect5521"
width="51.59375"
height="6.614583"
x="141.55208"
y="37.041668" />
<rect
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
id="rect5523"
width="70.114586"
height="6.614583"
x="125.67709"
y="47.625" />
<rect
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
id="rect5525"
width="78.052086"
height="6.614583"
x="126.99999"
y="58.208332" />
<rect
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
id="rect5527"
width="63.5"
height="6.614583"
x="129.64583"
y="68.791664" />
<rect
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
id="rect5529"
width="59.53125"
height="6.614583"
x="144.19792"
y="79.375" />
<rect
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
id="rect5531"
width="48.947918"
height="6.614583"
x="141.55208"
y="89.958336" />
<rect
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
id="rect5533"
width="47.625"
height="6.614583"
x="141.55208"
y="100.54166" />
<rect
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
id="rect5535"
width="44.979168"
height="18.520834"
x="156.10417"
y="112.44791" />
<path
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="m 17.197917,37.041666 v 5.291667"
id="path5593" />
<path
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="M 58.208334,29.104167 H 37.041667 v 63.5 h 5.291667"
id="path5609" />
<path
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="m 37.041667,82.020833 h 5.291667"
id="path5611" />
<path
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="m 37.041667,71.4375 h 5.291667"
id="path5613" />
<path
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="m 37.041667,60.854167 h 5.291667"
id="path5615" />
<path
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="m 37.041667,50.270834 h 5.291667"
id="path5617" />
<path
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="m 37.041667,39.687501 h 5.291667"
id="path5619" />
<path
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="M 83.343749,13.229167 H 17.197916 v 17.197916"
id="path5621" />
<circle
id="path5623"
style="fill:#000000;stroke:none;stroke-width:0.264583"
cx="37.041668"
cy="39.6875"
r="0.39749998" />
<circle
id="path5625"
style="fill:#000000;stroke:none;stroke-width:0.264583"
cx="37.041668"
cy="50.270832"
r="0.39749998" />
<circle
id="path5627"
style="fill:#000000;stroke:none;stroke-width:0.264583"
cx="37.041668"
cy="60.854164"
r="0.39749998" />
<circle
id="path5629"
style="fill:#000000;stroke:none;stroke-width:0.264583"
cx="37.041668"
cy="71.4375"
r="0.39749998" />
<circle
id="path5631"
style="fill:#000000;stroke:none;stroke-width:0.264583"
cx="37.041668"
cy="82.020836"
r="0.39749998" />
<path
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="m 109.80208,13.229167 h 7.9375 v 6.614583"
id="path5633" />
<path
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="M 115.09375,26.458333 V 109.80208 H 92.604166"
id="path5635" />
<path
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="M 88.635416,30.427083 H 146.84375"
id="path5637" />
<circle
id="path5639"
style="fill:#000000;stroke:none;stroke-width:0.264583"
cx="115.09375"
cy="30.427082"
r="0.39749998" />
<path
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="m 191.82291,30.427083 h 15.875 V 119.0625 h -6.61458"
id="path5641" />
<path
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="m 207.69791,39.6875 -14.55208,0"
id="path5643"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="m 207.69791,50.270833 -11.90624,0"
id="path5645"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="M 207.69791,71.437499 H 193.14583"
id="path5647" />
<path
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="M 207.69791,92.604166 H 190.5"
id="path5649" />
<path
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="M 207.69791,103.1875 H 189.17708"
id="path5651" />
<circle
id="path5653"
style="fill:#000000;stroke:none;stroke-width:0.264583"
cx="207.69791"
cy="103.1875"
r="0.39749998" />
<circle
id="path5655"
style="fill:#000000;stroke:none;stroke-width:0.264583"
cx="207.69791"
cy="92.604164"
r="0.39749998" />
<circle
id="path5657"
style="fill:#000000;stroke:none;stroke-width:0.264583"
cx="207.69791"
cy="71.4375"
r="0.39749998" />
<circle
id="path5659"
style="fill:#000000;stroke:none;stroke-width:0.264583"
cx="207.69791"
cy="50.270832"
r="0.39749998" />
<circle
id="path5661"
style="fill:#000000;stroke:none;stroke-width:0.264583"
cx="207.69791"
cy="39.6875"
r="0.39749998" />
<path
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="m 125.67708,50.270833 h -3.96875 l 0,10.583333 H 127"
id="path5663"
sodipodi:nodetypes="cccc" />
<path
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
d="m 129.64583,71.437499 h -5.29166 v 10.583333 h 19.84374"
id="path5665" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 21 KiB

View File

@ -414,4 +414,3 @@ Bazel\\
\subsection{Часть сценария одной из лекций}
\end{document}

View File

@ -1 +0,0 @@
Ovchinnikov_II@OVCHINNIKOV_II.21588:1669277770

BIN
seminars/build/jtc1-01c.pdf Normal file

Binary file not shown.

BIN
seminars/build/jtc1-02c.pdf Normal file

Binary file not shown.

BIN
seminars/build/jtc3-03c.pdf Normal file

Binary file not shown.

BIN
seminars/build/jtc4-04c.pdf Normal file

Binary file not shown.

364
seminars/jtc1-01c.tex Normal file
View File

@ -0,0 +1,364 @@
\documentclass[../j-spec.tex]{subfiles}
\begin{document}
\sloppy
\section{Семинар: компиляция и интерпретация кода}
\subsection{Инструментарий}
\begin{itemize}
\item \href{https://docs.google.com/presentation/d/1LPMWfXpjkJDOMR4lv7y5Ss6_ABSocZtoc7nVEVs6FQo}{Презентация для преподавателя}, ведущего семинар;
\item \href{https://drive.google.com/file/d/1LWyE8aEy4-1gsognqhXIXwDcoLviVge4/view}{Фон} GeekBrains для проведения семинара в Zoom;
\item \href{https://jupyter.org/install}{Jupyter Notebook} для практики и примеров используется Jupyter notebook (потребуется установить \href{https://www.python.org/downloads/}{Python} и ядро \href{https://github.com/SpencerPark/IJava}{IJava}) и любой терминал операционной системы (bash, zsh, cmd);
\item JDK любая 11 версии и выше;
\item \href{https://docs.docker.com/get-docker}{Docker}, \href{https://www.gnu.org/software/automake/}{make}.
\end{itemize}
\subsection{Цели семинара}
\begin{itemize}
\item Закрепить полученные на лекции знания, касающиеся компиляции, интерпретации кода и создания программной документации;
\item Получить практический навык настройки терминала ОС для компиляции и исполнения кода, установки сторонних библиотек для интерпретации;
\item Попрактиковаться в написании терминальных команд и простых проектов. Лучше понять принцип импортирования кода и сборки проекта.
\end{itemize}
\subsection{План-содержание}
\noindent
\begin{spreadtab}{{longtable}{|p{37mm}|l|l|p{90mm}|}}
\hline
@ Что происходит & @ Время & @ Слайды & @ Описание \\
\hline
\endhead
@ Организационный момент & 5 tag(beg) & @ 1-4 & @ Преподаватель ожидает студентов, поддерживает активность и коммуникацию в чате, озвучиает цели и планы на семинар. Важно упомянуть, что выполнение домашних заданий с лекции является, фактически, подготовкой к семинару \\
\hline
@ Quiz & 5 & @ 3-14 & @ Преподаватель задаёт вопросы викторины, через 30 секунд демонстрирует слайд-подсказку и ожидает ответов (4 вопроса, по минуте на ответ) \\
\hline
@ Рассмотрение ДЗ & 15 & @ 15-18 & @ Преподаватель демонстрирует свой вариант решения домашнего задания с лекции, возможно, по предварительному опросу, демонстрирует и разбирает вариант решения одного из студентов \\
\hline
@ Вопросы и ответы & 10 & @ 19 & @ Преподаватель ожидает вопросов по теме прошедшей лекции, викторины и продемонстрированной работы \\
\hline
@ Задание 1 & 10 & @ 20-22 & @ Создать, скомпилировать, запустить и продемонстрировать простой проект без использования среды разработки. Показать выполненные терминальные команды, результат компиляции. (* отделить исходный код от скомпилированных файлов, ** сложить исходный код в пакет) \\
\hline
@ Перерыв (если нужен) & 5 & @ 26 & @ Преподаватель предлагает студентам перерыв на 5 минут (студенты голосуют) \\
\hline
@ Задание 2 & 10 & @ 23-25 & @ Настроить окружение Jupyter Notebook с ядром Java, создать одну ячейку с переменной, а вторую с выводом значения этой переменной стандартным способом. Дополнить ячейки описанием markdown. (* осуществить форматированный вывод, ** сохранить форматирующую строку в ячейке с переменной) \\
\hline
@ Задание 3 & 15 & @ 27-29 & @ К проекту из задания 1 добавить ещё один класс в соседнем пакете, как это было показано на лекции и комментарии в стиле Javadoc. Комментарии необходимо добавить как к методам, так и к классам. Сгенерировать программную документацию. (* создать документацию на каждый пакет по отдельности) \\
\hline
@ Домашнее задание & 5 & @ 39 & @ Объясните домашнее задание, подведите итоги урока \\
\hline
@ Рефлексия & 10 tag(end) & @ 40-42 & @ Преподаватель запрашивает обратную связь \\
\hline
@ Длительность & sum(cell(beg):cell(end)) & & \\
\hline
\end{spreadtab}
\subsection{Подробности}
\subsubsection{Организационный момент}
\begin{itemize}
\item \textbf{Цель этапа:} Позитивно начать урок, создать комфортную среду для обучения.
\item \textbf{Тайминг:} 3-5 минут.
\item \textbf{Действия преподавателя:}
\begin{itemize}
\item Презентует название курса (первый раз) и семинара;
\item Рассказывает немного о себе;
\item Запрашивает активность от аудитории в чате;
\item Презентует цели курса и семинара;
\item Презентует краткий план семинара и что студент научится делать.
\end{itemize}
\end{itemize}
\subsubsection{Quiz}
\begin{itemize}
\item \textbf{Цель этапа:} Вовлечение аудитории в обратную связь.
\item \textbf{Тайминг:} 5-7 минут (4 вопроса, по минуте на ответ).
\item \textbf{Действия преподавателя:}
\begin{itemize}
\item Преподаватель задаёт вопросы викторины, представленные на слайдах презентации;
\item через 30 секунд демонстрирует слайд-подсказку и ожидает ответов.
\end{itemize}
\item \textbf{Вопросы и ответы:}
\begin{enumerate}
\item Какой механизм используется для непосредственного исполнения скомпилированного кода? (3)
\begin{enumerate}
\item JDK;
\item JRE;
\item JVM.
\end{enumerate}
\item Какая сущность только объединяет классы по смыслу? (1)
\begin{enumerate}
\item Пакеты;
\item Библиотеки;
\item Фреймворки.
\end{enumerate}
\item Основная единица исходного кода программы -- это? (2)
\begin{enumerate}
\item Функция;
\item Класс;
\item Файл.
\end{enumerate}
\item Какой ключ используется для указания папки назначения? (1)
\begin{enumerate}
\item \code{-d};
\item \code{-out};
\item \code{-to}.
\end{enumerate}
\end{enumerate}
\end{itemize}
\subsubsection{Рассмотрение ДЗ}
\begin{itemize}
\item \textbf{Цель этапа:} Пояснить неочевидные моменты в формулировке ДЗ с лекции, синхронизировать прочитанный на лекции материал к началу семинара.
\item \textbf{Тайминг:} 15-20 минут.
\item \textbf{Действия преподавателя:}
\begin{itemize}
\item Преподаватель демонстрирует свой вариант решения домашнего задания из лекции;
\item возможно, по предварительному опросу, демонстрирует и разбирает вариант решения одного из студентов.
\end{itemize}
\item \textbf{Домашнее задание из лекции:}
\begin{itemize}
\item Создать проект из трёх классов (основной с точкой входа и два класса в другом пакете), которые вместе должны составлять одну программу, позволяющую производить четыре основных математических действия и осуществлять форматированный вывод результатов пользователю.
\textbf{Вариант решения}
\begin{figure}[H]
\centering
\includegraphics[width=100mm]{sem-01-struct.png}
\caption{Структура проекта}
\end{figure}
\lstinputlisting[language=Java,style=JCodeStyle,caption={Код основного класса}]{src/s01-h01-Main.java}
\lstinputlisting[language=Java,style=JCodeStyle,caption={Код считающего класса}]{src/s01-h01-OtherClass.java}
\lstinputlisting[language=Java,style=JCodeStyle,caption={Код декоратора}]{src/s01-h01-Decorator.java}
\item Скомпилировать проект, а также создать для этого проекта стандартную веб-страницу с документацией ко всем пакетам.
\textbf{Вариант решения}
\begin{lstlisting}[language=bash,style=ASMStyle,caption={Команды компиляции}]
javac -sourcepath ./src -d out src/ru/gb/jcore/sample/Main.java
java -classpath ./out ru.gb.jcore.sample.Main
\end{lstlisting}
\begin{figure}[H]
\centering
\includegraphics[width=60mm]{sem-01-hw2-compile.png}
\caption{Результат компиляции}
\end{figure}
\begin{lstlisting}[language=bash,style=ASMStyle,caption={Команда создания документации}]
javadoc -d docs -sourcepath ./src -cp ./out -subpackages ru
\end{lstlisting}
\begin{figure}[H]
\centering
\includegraphics[width=120mm]{sem-01-hw2-doc.png}
\caption{Результат создания документации}
\end{figure}
\item Создать Makefile с задачами сборки, очистки и создания документации на весь проект.
\textbf{Вариант решения}\footnote{Обратите внимание, что все отступы сделаны не пробелами, а табуляцией, иначе Makefile не работает}
\lstinputlisting[style=CCodeStyle,caption={Makefile}]{src/s01-h03-Makefile}
\begin{figure}[H]
\centering
\includegraphics[width=80mm]{sem-01-hw03.png}
\caption{Результат выполнения тасков}
\end{figure}
\item *Создать два Docker-образа. Один должен компилировать Java-проект обратно в папку на компьютере пользователя, а второй забирать скомпилированные классы и исполнять их.
\textbf{Вариант решения}
Для упрощения был использован docker compose, вместо чистого Docker. Файлы, компилирующие и исполняющие программу представлены в листингах ниже. Оба эти файла запускаются из корня папки проекта командами
\begin{verbatim}
docker compose -f docker-compose-class.yml up
docker compose -f docker-compose-exec.yml up
\end{verbatim}
соответственно.
\lstinputlisting[style=CCodeStyle,caption={docker-compose-class.yml}]{src/s01-h04-docker-compose-class.yml}
\lstinputlisting[style=CCodeStyle,caption={docker-compose-exec.yml}]{src/s01-h04-docker-compose-exec.yml}
\end{itemize}
\end{itemize}
\subsubsection{Вопросы и ответы}
\begin{itemize}
\item \textbf{Ценность этапа} Вовлечение аудитории в обратную связь, пояснение неочевидных моментов в материале лекции и другой проделанной работе.
\item \textbf{Тайминг} 5-15 минут
\item \textbf{Действия преподавателя}
\begin{itemize}
\item Преподаватель ожидает вопросов по теме прошедшей лекции, викторины и продемонстрированной работы;
\item Если преподаватель затрудняется с ответом, необходимо мягко предложить студенту ответить на его вопрос на следующем семинаре (и не забыть найти ответ на вопрос студента!);
\item Предложить и показать пути самостоятельного поиска студентом ответа на заданный вопрос;
\item Посоветовать литературу на тему заданного вопроса;
\item Дополнительно указать на то, что все сведения для выполнения домашнего задания, прохождения викторины и работы на семинаре были рассмотрены в методическом материале к этому или предыдущим урокам.
\end{itemize}
\end{itemize}
\subsubsection{Задание 1}
\begin{itemize}
\item \textbf{Ценность этапа} Создание, компиляция и запуск проектов без использования среды разработки.
\item \textbf{Тайминг} 10-20 минут.
\item \textbf{Действия преподавателя}
\begin{itemize}
\item Пояснить студентам ценность этого опыта (запуск приложений на сервере, в контейнерах, настройка CI/CD в пет-проектах);
\item Выдать задание группам студентов, показать где именно следует искать терминал ОС;
\item Если группа студентов справилась с заданием, а времени осталось более 5 минут, выдавать группе задания «со звёздочкой».
\end{itemize}
\item \textbf{Задания}:
\begin{itemize}
\item Создать, скомпилировать, запустить и продемонстрировать простой проект без использования среды разработки.
\textbf{Вариант решения}
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Простейший проект}]
public class Main {
public static void main(String[] args) {
System.out.println("Hello, world!");
}
}
\end{lstlisting}
\begin{lstlisting}[language=bash,style=ASMStyle,caption={Команды компиляции}]
javac Main.java
java Main
\end{lstlisting}
\item [$*_1$] отделить исходный код от скомпилированных файлов
\textbf{Вариант решения}
\begin{lstlisting}[style=ASMStyle]
javac -d out Main.java
java -classpath ./out Main
\end{lstlisting}
\item [$*_2$] сложить исходный код в пакет с глубиной иерархии не менее 3.
\textbf{Вариант решения}
Вручную создать соответствующие вложенные папки, переместить в них файл с исходным кодом \code{Main.java} и написать оператор \code{package} первой строкой файла \code{Main.java}.
\begin{lstlisting}[style=ASMStyle]
javac -d out ru/gb/jcore/Main.java
java -classpath ./out ru.gb.jcore.Main
\end{lstlisting}
\end{itemize}
\end{itemize}
\subsubsection{Задание 2}
\begin{itemize}
\item \textbf{Ценность этапа} Настройка и изучение дополнительного инструментария для создания проектов и описания работы фрагментов кода в виде Jupyter notebook.
\item \textbf{Тайминг} 10-15 минут.
\item \textbf{Действия преподавателя}
\begin{itemize}
\item Пояснить студентам ценность этого опыта (использование скриптовых возможностей среды разработки, таких как написание простых фрагментов кода без необходимости создавать большой проект в тяжеловесной среде разработки);
\item Пояснить студентам в каком виде выполнять и сдавать задания;
\item Выдать задание группам студентов, показать где и как скачивать необходимый инструментарий, если он ещё не установлен;
\item Если группа студентов справилась с заданием, а времени осталось более 5 минут, выдавать группе задания «со звёздочкой».
\end{itemize}
\item \textbf{Задания}
\begin{itemize}
\item Настроить окружение Jupyter Notebook с ядром IJava, создать одну ячейку с переменной, а вторую с выводом значения этой переменной стандартным способом. Дополнить ячейки описанием markdown.
\begin{figure}[H]
\centering
\includegraphics[width=120mm]{sem-01-t2-1.png}
\caption{Вариант решения}
\end{figure}
\item [$*_1$] осуществить форматированный вывод
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Вариант решения (вторая ячейка)}]
System.out.print("Your number is " + a);
\end{lstlisting}
\item [$*_2$] сохранить форматирующую строку в ячейке с переменной
\begin{figure}[H]
\centering
\includegraphics[width=120mm]{sem-01-t2-2.png}
\caption{Вариант решения}
\end{figure}
\end{itemize}
\end{itemize}
\subsubsection{Задание 3}
\begin{itemize}
\item \textbf{Ценность этапа} Закрепление навыков создания стандартной программной документации.
\item \textbf{Тайминг} 15-20 минут
\item \textbf{Действия преподавателя}
\begin{itemize}
\item Пояснить студентам ценность этого опыта (описание пет-проектов для потенциальных соисполнителей, создание базы знаний по проекту на случай длительных пауз в работе)
\item Выдать задание группам студентов
\item Если группа студентов справилась с заданием, а времени осталось более 5 минут, выдать группе задание «со звёздочкой».
\end{itemize}
\item \textbf{Задания}
\begin{itemize}
\item К проекту из задания 1 добавить ещё один класс в соседнем пакете, как это было показано на лекции, и комментарии в стиле Javadoc. Комментарии необходимо добавить как к методам, так и к классам. Сгенерировать общую программную документацию.
\textbf{Вариант решения}
\begin{figure}[H]
\centering
\includegraphics[width=80mm]{sem-01-t3-1.png}
\caption{Иерархия получившегося проекта}
\end{figure}
\lstinputlisting[language=Java,style=JCodeStyle,caption={Основной класс}]{src/s01-t3-Simple.java}
\lstinputlisting[language=Java,style=JCodeStyle,caption={Вспомогательный класс}]{src/s01-t3-Complex.java}
\begin{lstlisting}[language=bash,style=ASMStyle,caption={Команды компиляции и создания документации}]
javac -sourcepath . -d out ru/gb/Simple.java
java -classpath ./out ru.gb.Simple
javadoc -d doc -sourcepath . -cp ./out -subpackages ru
\end{lstlisting}
\item [$*_1$] создать документацию на каждый пакет по отдельности
\begin{lstlisting}[language=bash,style=ASMStyle,caption={Вариант решения}]
javadoc -d doc_gb -sourcepath . -cp ./out ru.gb
javadoc -d doc_bg -sourcepath . -cp ./out ru.bg
\end{lstlisting}
\end{itemize}
\end{itemize}
\subsubsection{Домашнее задание}
\begin{itemize}
\item \textbf{Ценность этапа} Задать задание для самостоятельного выполнения между занятиями.
\item \textbf{Тайминг} 5-10 минут.
\item \textbf{Действия преподавателя}
\begin{itemize}
\item Пояснить студентам в каком виде выполнять и сдавать задания
\item Уточнить кто будет проверять работы (преподаватель или ревьювер)
\item Объяснить к кому обращаться за помощью и где искать подсказки
\item Объяснить где взять проект заготовки для дз
\end{itemize}
\item \textbf{Задания}
\begin{enumerate}
\item [5-25 мин] Решить все задания (в том числе «со звёздочкой»), если они не были решены на семинаре, без ограничений по времени;
Все варианты решения приведены в тексте семинара выше
\item [10-15 мин] Создать docker-контейнер для формирования полной документации по проекту
\lstinputlisting[style=CCodeStyle,caption={docker-compose-class.yml}]{src/s01-hw2-docker-compose-docs.yml}
\end{enumerate}
\end{itemize}
\subsubsection{Рефлексия и завершение семинара}
\begin{itemize}
\item \textbf{Цель этапа:} Привести урок к логическому завершению, посмотреть что студентам удалось, что было сложно и над чем нужно еще поработать
\item \textbf{Тайминг:} 5-10 минут
\item \textbf{Действия преподавателя:}
\begin{itemize}
\item Запросить обратную связь от студентов.
\item Подчеркните то, чему студенты научились на занятии.
\item Дайте рекомендации по решению заданий, если в этом есть необходимость
\item Дайте краткую обратную связь студентам.
\item Поделитесь ощущением от семинара.
\item Поблагодарите за проделанную работу.
\end{itemize}
\end{itemize}
\end{document}

429
seminars/jtc1-02c.tex Normal file
View File

@ -0,0 +1,429 @@
\documentclass[../j-spec.tex]{subfiles}
\usepackage{spreadtab}
\begin{document}
\setcounter{section}{1}
\section{Семинар: данные и функции}
\subsection{Инструментарий}
\begin{itemize}
\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.
\end{itemize}
\subsection{Цели семинара}
\begin{itemize}
\item Закрепить полученные на лекции знания, хранения примитивных и ссылочных типов данных;
\item Получить практический навык создания функций по описанию;
\item Попрактиковаться в написании простых функций, манипулирующих ссылочными данными.
\end{itemize}
\subsection{План-содержание}
\noindent
\begin{spreadtab}{{longtable}{|p{37mm}|l|l|p{90mm}|}}
\hline
@ Что происходит & @ Время & @ Слайды & @ Описание \\
\hline
\endhead
@ Организационный момент & 5 tag(beg) & @ 1-5 & @ Преподаватель ожидает студентов, поддерживает активность и коммуникацию в чате, озвучиает цели и планы на семинар. Важно упомянуть, что выполнение домашних заданий с лекции является, фактически, подготовкой к семинару \\
\hline
@ Quiz & 5 & @ 6-18 & @ Преподаватель задаёт вопросы викторины, через 30 секунд демонстрирует слайд-подсказку и ожидает ответов (4 вопроса, по минуте на ответ) \\
\hline
@ Рассмотрение ДЗ лекции & 10 & @ 19-23 & @ Преподаватель демонстрирует свой вариант решения домашнего задания с лекции, возможно, по предварительному опросу, демонстрирует и разбирает вариант решения одного из студентов \\
\hline
@ Вопросы и ответы & 10 & @ 24 & @ Преподаватель ожидает вопросов по теме прошедшей лекции, викторины и продемонстрированной работы \\
\hline
@ Задание 1 & 10 & @ 25-28 & @ Сравнить насколько разные могут быть прочтения одного и того же технического задания - одна функция для двух значений, возврат значений, возврат индекса, объявление исходного массива внутри функции поиска и др); \\
\hline
@ Задание 2 & 10 & @ 29-32 & @ Корректная манипуляция индексами, как следствие, сокращение числа возможных проходов по массиву и ускорение работы приложени \\
\hline
@ Перерыв (если нужен) & 5 & @ 33 & @ Преподаватель предлагает студентам перерыв на 5 минут (студенты голосуют) \\
\hline
@ Задание 3 & 20 & @ 34-37 & @ Формирование алгоритмического мышления при решении задач с описанием верхнего уровня \\
\hline
@ Задание 4 & 15 & @ 38-41 & @ Понимание внутренней механики работы фреймворка коллекций, повышение уровня абстракции написанного кода \\
\hline
@ Задание 5 (необязат) & 20 & @ 42-44 & @ Описание базовых алгоритмов манипуляции данными с применением вспомогательных массивов \\
\hline
@ Домашнее задание & 5 & @ 45-46 & @ Объясните домашнее задание, подведите итоги урока \\
\hline
@ Рефлексия & 10 tag(end) & @ 47-48 & @ Преподаватель запрашивает обратную связь \\
\hline
@ Длительность & sum(cell(beg):cell(end)) & & \\
\hline
\end{spreadtab}
\subsection{Подробности}
\subsubsection{Организационный момент}
\begin{itemize}
\item \textbf{Цель этапа:} Позитивно начать урок, создать комфортную среду для обучения.
\item \textbf{Тайминг:} 3-5 минут.
\item \textbf{Действия преподавателя:}
\begin{itemize}
\item Презентует название курса (первый раз) и семинара;
\item Рассказывает немного о себе;
\item Запрашивает активность от аудитории в чате;
\item Презентует цели курса и семинара;
\item Презентует краткий план семинара и что студент научится делать.
\end{itemize}
\end{itemize}
\subsubsection{Quiz}
\begin{itemize}
\item \textbf{Цель этапа:} Вовлечение аудитории в обратную связь.
\item \textbf{Тайминг:} 5-7 минут (4 вопроса, по минуте на ответ).
\item \textbf{Действия преподавателя:}
\begin{itemize}
\item Преподаватель задаёт вопросы викторины, представленные на слайдах презентации;
\item через 30 секунд демонстрирует слайд-подсказку и ожидает ответов.
\end{itemize}
\item \textbf{Вопросы и ответы:}
\begin{enumerate}
\item Магическое число -- это: (1)
\begin{enumerate}
\item числовая константа без пояснений;
\item число, помогающее в вычислениях;
\item числовая константа, присваиваемая при объявлении переменной.
\end{enumerate}
\item Какое значение будет содержаться в переменной a после выполнения строки \code{int а = 10.0f/3.0f;} (3)
\item Сколько будет создано одномерных массивов при инициализации массива 3х3x3? (13)
\item \code{2 + 2 * 2 == 2 << 2 >> 1}? (false? 6 != 4)
\end{enumerate}
\end{itemize}
\subsubsection{Рассмотрение ДЗ}
\begin{itemize}
\item \textbf{Цель этапа:} Пояснить неочевидные моменты в формулировке ДЗ с лекции, синхронизировать прочитанный на лекции материал к началу семинара.
\item \textbf{Тайминг:} 15-20 минут.
\item \textbf{Действия преподавателя:}
\begin{itemize}
\item Преподаватель демонстрирует свой вариант решения домашнего задания из лекции;
\item возможно, по предварительному опросу, демонстрирует и разбирает вариант решения одного из студентов.
\end{itemize}
\item \textbf{Домашнее задание из лекции:}
\begin{itemize}
\item Написать метод «Шифр Цезаря», с булевым параметром зашифрования/расшифрования, и числовым ключом;
\textbf{Вариант решения}
\lstinputlisting[language=Java,style=JCodeStyle,caption={Шифр Цезаря}]{src/s02-h1-caesar.java}
\item Написать метод, принимающий на вход массив чисел и параметр \code{n}. Метод должен осуществить циклический (последний элемент при сдвиге становится первым) сдвиг всех элементов массива на n позиций;
\textbf{Вариант решения}
\lstinputlisting[language=Java,style=JCodeStyle,caption={Сдвиговый метод}]{src/s02-h2-shifter.java}
\item Написать метод, которому можно передать в качестве аргумента массив, состоящий строго из единиц и нулей (целые числа типа \code{int}). Метод должен заменить единицы в массиве на нули, а нули на единицы и не содержать ветвлений. Написать как можно больше вариантов метода
\textbf{Вариант решения}
\lstinputlisting[language=Java,style=JCodeStyle,caption={Инверсия}]{src/s02-h3-inverse.java}
\end{itemize}
\end{itemize}
\subsubsection{Вопросы и ответы}
\begin{itemize}
\item \textbf{Ценность этапа} Задать задание для самостоятельного выполнения между занятиями.
\item \textbf{Тайминг} 5-15 минут
\item \textbf{Действия преподавателя}
\begin{itemize}
\item Преподаватель ожидает вопросов по теме прошедшей лекции, викторины и продемонстрированной работы;
\item Если преподаватель затрудняется с ответом, необходимо мягко предложить студенту ответить на его вопрос на следующем семинаре (и не забыть найти ответ на вопрос студента!);
\item Предложить и показать пути самостоятельного поиска студентом ответа на заданный вопрос;
\item Посоветовать литературу на тему заданного вопроса;
\item Дополнительно указать на то, что все сведения для выполнения домашнего задания, прохождения викторины и работы на семинаре были рассмотрены в методическом материале к этому или предыдущим урокам.
\end{itemize}
\end{itemize}
\subsubsection{Задание 1}
\begin{itemize}
\item \textbf{Ценность этапа} Базовая манипуляция данными внутри массива.
\item \textbf{Тайминг} 10-15 минут.
\item \textbf{Действия преподавателя}
\begin{itemize}
\item Первые пять минут уклоняться от ответов на уточняющие вопросы
\item Пояснить студентам ценность опыта (сравнить насколько разные могут быть прочтения одного и того же технического задания - одна функция для двух значений, возврат значений, возврат индекса, объявление исходного массива внутри функции поиска и др);
\item Выдать задание группам студентов, показать где именно следует искать терминал ОС;
\item Если группа студентов справилась с заданием, а времени осталось более 5 минут, выдавать группе задания «со звёздочкой».
\end{itemize}
\item \textbf{Задания}:
\begin{itemize}
\item Задать одномерный массив. Написать методы поиска в нём минимального и максимального элемента;
\textbf{Вариант решения}
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Поиск минимального значения}]
private static int findMin(int[] a) { // returns the minimum value
int min = a[0];
for (int i = 1; i < a.length; i++) {
if (a[i] < min) {
min = a[i];
}
}
return min;
}
\end{lstlisting}
\item [$*_1$] Привести функции к корректному виду и дополнительно написать ещё две функции так, чтобы получились (четыре) функции поиска минимального и максимального как значения, так и индекса.
\textbf{Вариант решения}
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Поиск индекса максимального значения}]
private static int findMax(int[] a) { // returns the maximum index
int max = 0;
for (int i = 1; i < a.length; i++) {
if (a[i] > a[max])
max = i;
}
return max;
}
\end{lstlisting}
\end{itemize}
\end{itemize}
\subsubsection{Задание 2}
\begin{itemize}
\item \textbf{Ценность этапа} Оптимизация сложности алгоритмов при работе с многомерными массивами.
\item \textbf{Тайминг} 10-15 минут.
\item \textbf{Действия преподавателя}
\begin{itemize}
\item Пояснить студентам ценность этого опыта (корректная манипуляция индексами, как следствие, сокращение числа возможных проходов по массиву и ускорение работы приложения);
\item Пояснить студентам в каком виде выполнять и сдавать задания;
\item Выдать задание группам студентов, показать где и как скачивать необходимый инструментарий, если он ещё не установлен;
\item Если группа студентов справилась с заданием, а времени осталось более 5 минут, выдавать группе задания «со звёздочкой».
\end{itemize}
\item \textbf{Задания}
\begin{itemize}
\item Создать квадратный целочисленный массив (количество строк и столбцов одинаковое), заполнить его диагональные элементы единицами, используя цикл(ы)
\textbf{Вариант решения}
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Заполнение диагональных элементов}]
private static void fillDiagonal(int[][] a) {
for (int i = 0; i < a.length; i++) {
a[i][i] = 1;
a[i][a.length - 1 - i] = 1;
}
}
\end{lstlisting}
\item [$*_1$] дописать функцию вывода двумерного массива в консоль
\textbf{Вариант решения}
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Вывод массива в терминал}]
private static void printTwoDimArray(int[][] a) {
for (int i = 0; i < a.length; i++) {
System.out.println(Arrays.toString(a[i]));
}
}
\end{lstlisting}
\end{itemize}
\end{itemize}
\subsubsection{Задание 3}
\begin{itemize}
\item \textbf{Ценность этапа} Формирование алгоритмического мышления при решении задач с описанием верхнего уровня.
\item \textbf{Тайминг} 15-20 минут
\item \textbf{Действия преподавателя}
\begin{itemize}
\item Пояснить студентам ценность этого опыта (ТЗ довольно редко бывают чёткими и никогда не говорят программисту, что именно нужно написать);
\item Выдать задание группам студентов;
\item Если группа студентов справилась с заданием, а времени осталось более 5 минут, выдать группе задание «со звёздочкой».
\end{itemize}
\item \textbf{Задания}
\begin{itemize}
\item Написать метод, в который передается не пустой одномерный целочисленный массив, метод должен вернуть true если в массиве есть место, в котором сумма левой и правой части массива равны. Примеры:
\begin{itemize}
\item [] \code{checkBalance([1, 1, 1, || 2, 1])} $\to$ \code{true},
\item [] \code{checkBalance([2, 1, 1, 2, 1])} $\to$ \code{false},
\item [] \code{checkBalance([10, || 1, 2, 3, 4])} $\to$ \code{true}.
\end{itemize}
Абстрактная граница показана символами \code{||}, эти символы в массив не входят.
\textbf{Вариант решения}
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Вариант со сложностью $O(n^2)$}]
private static boolean checkBalance(int[] a) {
int left = 0;
for (int i = 0; i < a.length - 1; i++) {
left += a[i];
int right = 0;
for (int j = i + 1; j < a.length; j++) {
right += a[j];
}
if (left == right) return true;
}
return false;
}
\end{lstlisting}
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Вариант со сложностью $O(2n)$}]
private static boolean checkBalance2(int[] a) {
int sum = 0;
for (int i = 0; i < a.length; i++) {
sum += a[i];
}
if (sum % 2 != 0) return false;
int left = 0;
for (int i = 0; i < a.length; i++) {
left += a[i];
sum -= a[i];
if (left == sum) return true;
}
return false;
}
\end{lstlisting}
\item [$*_1$] написать этот же метод таким образом, чтобы в нём использовался только один цикл.
\textbf{Вариант решения}
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={* Вариант со сложностью $O(n)$}]
private static boolean checkBalance3(int[] a) {
int lbound = 0;
int rbound = a.length - 1;
int left = 0;
int right = 0;
while (lbound <= rbound) {
if (left > right)
right += a[rbound--];
else
left += a[lbound++];
}
return left == right;
}
\end{lstlisting}
\end{itemize}
\end{itemize}
\subsubsection{Задание 4}
\begin{itemize}
\item \textbf{Ценность этапа} Понимание внутренней механики работы фреймворка коллекций, повышение уровня абстракции написанного кода.
\item \textbf{Тайминг} 15-20 минут
\item \textbf{Действия преподавателя}
\begin{itemize}
\item Пояснить студентам ценность этого опыта (написание собственных функций, реализующих алгоритмы часто помогает в ситуациях, когда задача не решается стандартными средствами)
\item Выдать задание группам студентов
\item Если группа студентов справилась с заданием, а времени осталось более 5 минут, выдать группе задание «со звёздочкой».
\item Если нужно, через 7 минут после старта, дать подсказку для первой части задания (сигнатура функции должна содержать не только передаваемый массив, но и его текущее заполнение, которое нужно отслеживать самостоятельно)
\end{itemize}
\item \textbf{Задания}
\begin{itemize}
\item Написать функцию добавления элемента в конец массива таким образом, чтобы она расширяла массив при необходимости.
Здесь нет смысла показывать не лучшее, но самое популярное решение, поэтому можно продемонстрировать сразу вариант решения «со звёздочкой».
\item [$*_1$] Функция должна возвращать ссылку на вновь созданный внутри себя массив, а не использовать глобальный
\textbf{Вариант решения}
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={* Вариант без глобального массива}]
int[] add(int[] arr, int current, int value) {
if (current == arr.length) {
int[] temp = new int[arr.length * 2];
System.arraycopy(arr, 0, temp, 0, arr.length);
arr = temp;
}
arr[current++] = value;
return arr;
}
// main
int[] array = {1,2};
int size = 2;
System.out.println(size + " = " + Arrays.toString(array));
array = add(array, size++, 6);
System.out.println(size + " = " + Arrays.toString(array));
array = add(array, size++, 6);
\end{lstlisting}
\end{itemize}
\end{itemize}
\subsubsection{Задание 5 (необязательное)}
\begin{itemize}
\item \textbf{Ценность этапа} Описание базовых алгоритмов манипуляции данными с применением вспомогательных массивов.
\item \textbf{Тайминг} 15-20 минут
\item \textbf{Действия преподавателя}
\begin{itemize}
\item Объяснить студентам, в чём заключается алгоритм сортировки подсчётом. Для сортировки подсчётом алгоритм совершает проход по исходному массиву, подсчитывая количество повторений каждого значения, и записывая эту информацию в промежуточный (частотный) массив. Вторым шагом алгоритма совершается обход вспомогательного массива и запись нужного количества значений по возрастанию в исходный массив. Сложность сортировки $O(2n)$. Например:
\[ x[2,1,0,4,3,0,0,1,2] \to t[3(x_0),2(x_1),2(x_2),1(x_3),1(x_4)] \to x[0,0,0,1,1,2,2,3,4] \]
\item Выдать задание группам студентов
\item Если группа студентов справилась с заданием, а времени осталось более 5 минут, выдать группе задание «со звёздочкой».
\end{itemize}
\item \textbf{Задания}
\begin{itemize}
\item Написать метод, осуществляющий сортировку одномерного массива подсчётом. Важное ограничение состоит в том, что для этой сортировки диапазон значений исходного массива должен находиться в разумных пределах, например, не более 1000.
\textbf{Вариант решения}
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Pigeonhole sort}]
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 < arr.length; i++)
freq[arr[i] - min]++;
int arrIndex = 0;
for (int i = 0; i < freq.length; i++)
for (int elems = freq[i]; elems > 0; elems--)
arr[arrIndex++] = i + min;
}
\end{lstlisting}
\end{itemize}
\end{itemize}
\subsubsection{Домашнее задание}
\begin{itemize}
\item \textbf{Ценность этапа} Задать задание для самостоятельного выполнения между занятиями.
\item \textbf{Тайминг} 5-10 минут.
\item \textbf{Действия преподавателя}
\begin{itemize}
\item Пояснить студентам в каком виде выполнять и сдавать задания
\item Уточнить кто будет проверять работы (преподаватель или ревьювер)
\item Объяснить к кому обращаться за помощью и где искать подсказки
\item Объяснить где взять проект заготовки для дз
\end{itemize}
\item \textbf{Задания}
\begin{enumerate}
\item [5-25 мин] Решить все задания (в том числе «со звёздочкой»), если они не были решены на семинаре, без ограничений по времени;
Все варианты решения приведены в тексте семинара выше
\item [5-10 мин] Написать метод, возвращающий количество чётных элементов массива.
\begin{itemize}
\item [] \code{countEvens([2, 1, 2, 3, 4])} $\to$ \code{3}
\item [] \code{countEvens([2, 2, 0])} $\to$ \code{3}
\item [] \code{countEvens([1, 3, 5])} $\to$ \code{0}
\end{itemize}
\lstinputlisting[language=Java,style=JCodeStyle,caption={CountEvens.java}]{src/s02-hw2-count.java}
\item [10 мин] Написать функцию, возвращающую разницу между самым большим и самым маленьким элементами переданного не пустого массива.
\lstinputlisting[language=Java,style=JCodeStyle,caption={Spread.java}]{src/s02-hw2-spread.java}
\item [10 мин] Написать функцию, возвращающую истину, если в переданном массиве есть два соседних элемента, с нулевым значением.
\lstinputlisting[language=Java,style=JCodeStyle,caption={Zero2.java}]{src/s02-hw2-zeros.java}
\end{enumerate}
\end{itemize}
\subsubsection{Рефлексия и завершение семинара}
\begin{itemize}
\item \textbf{Цель этапа:} Привести урок к логическому завершению, посмотреть что студентам удалось, что было сложно и над чем нужно еще поработать
\item \textbf{Тайминг:} 5-10 минут
\item \textbf{Действия преподавателя:}
\begin{itemize}
\item Запросить обратную связь от студентов.
\item Подчеркните то, чему студенты научились на занятии.
\item Дайте рекомендации по решению заданий, если в этом есть необходимость
\item Дайте краткую обратную связь студентам.
\item Поделитесь ощущением от семинара.
\item Поблагодарите за проделанную работу.
\end{itemize}
\end{itemize}
\end{document}

549
seminars/jtc3-03c.tex Normal file
View File

@ -0,0 +1,549 @@
\documentclass[../j-spec.tex]{subfiles}
\usepackage{spreadtab}
\begin{document}
\setcounter{section}{2}
\section{Семинар: классы и объекты}
\subsection{Инструментарий}
\begin{itemize}
\item \href{https://docs.google.com/presentation/d/1qaEt-5sSLYWeP_FSvL2uJiLwEFLYfNFg_iCvnUr3dqo}{Презентация} для преподавателя, ведущего семинар;
\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.
\end{itemize}
\subsection{Цели семинара}
\begin{itemize}
\item Закрепить полученные на лекции знания об объектах, наследовании и полиморфизме;
\item Получить практический навык создания классов по описанию;
\item Дополнительно рассмотреть использование свойств статичности сущностей, неочевидные случаи несоблюдения инкапсуляции;
\item Попрактиковаться в написании простых классов и методов, манипулирующих ссылочными данными.
\end{itemize}
\subsection{План-содержание}
\noindent
\begin{spreadtab}{{longtable}{|p{37mm}|l|l|p{90mm}|}}
\hline
@ Что происходит & @ Время & @ Слайды & @ Описание \\
\hline
\endhead
@ Организационный момент & 5 tag(beg) & @ 1-5 & @ Преподаватель ожидает студентов, поддерживает активность и коммуникацию в чате, озвучиает цели и планы на семинар. Важно упомянуть, что выполнение домашних заданий с лекции является, фактически, подготовкой к семинару \\
\hline
@ Quiz & 10 & @ 6-24 & @ Преподаватель задаёт вопросы викторины, через 30 секунд демонстрирует слайд-подсказку и ожидает ответов (6 вопросов, по минуте на ответ) \\
\hline
@ Рассмотрение ДЗ лекции & 10 & @ 25-30 & @ Преподаватель демонстрирует свой вариант решения домашнего задания с лекции, возможно, по предварительному опросу, демонстрирует и разбирает вариант решения одного из студентов \\
\hline
@ Вопросы и ответы & 10 & @ 31 & @ Преподаватель ожидает вопросов по теме прошедшей лекции, викторины и продемонстрированной работы \\
\hline
@ Задание 1 & 5 & @ 32-35 & @ Создание класса и объекта. \\
\hline
@ Задание 2 & 10 & @ 36-40 & @ Манипуляция информацией об объекте \\
\hline
@ Перерыв (если нужен) & 5 & @ 41 & @ Преподаватель предлагает студентам перерыв на 5 минут (студенты голосуют) \\
\hline
@ Задание 3 & 20 & @ 42-46 & @ Создание и манипуляция множествами объектов \\
\hline
@ Задание 4 & 15 & @ 47-51 & @ Манипуляции данными по условию, «массовое обслуживание» \\
\hline
@ Задание 5 (необязат) & 15 & @ 52-54 & @ Соблюдение атомарности методов, независимость методов от окружения \\
\hline
@ Домашнее задание & 5 & @ 55-56 & @ Объясните домашнее задание, подведите итоги урока \\
\hline
@ Рефлексия & 10 tag(end) & @ 57-58 & @ Преподаватель запрашивает обратную связь \\
\hline
@ Длительность & sum(cell(beg):cell(end)) & & \\
\hline
\end{spreadtab}
\subsection{Подробности}
\subsubsection{Организационный момент}
\begin{itemize}
\item \textbf{Цель этапа:} Позитивно начать урок, создать комфортную среду для обучения.
\item \textbf{Тайминг:} 3-5 минут.
\item \textbf{Действия преподавателя:}
\begin{itemize}
\item Запрашивает активность от аудитории в чате;
\item Презентует цели курса и семинара;
\item Презентует краткий план семинара и что студент научится делать.
\end{itemize}
\end{itemize}
\subsubsection{Quiz}
\begin{itemize}
\item \textbf{Цель этапа:} Вовлечение аудитории в обратную связь.
\item \textbf{Тайминг:} 5-7 минут (4 вопроса, по минуте на ответ).
\item \textbf{Действия преподавателя:}
\begin{itemize}
\item Преподаватель задаёт вопросы викторины, представленные на слайдах презентации;
\item через 30 секунд демонстрирует слайд-подсказку и ожидает ответов.
\end{itemize}
\item \textbf{Вопросы и ответы:}
\begin{enumerate}
\item Какое свойство добавляет ключевое слово static полю или методу? (2)
\begin{enumerate}
\item неизменяемость;
\item принадлежность классу;
\item принадлежность приложению.
\end{enumerate}
\item Что быстрее, стек или куча? (1)
\begin{enumerate}
\item куча;
\item стек;
\item одинаково.
\end{enumerate}
\item Для инициализации нового объекта абсолютно идентичными значениями свойств переданного объекта используется (3)
\begin{enumerate}
\item пустой конструктор;
\item конструктор по-умолчанию;
\item конструктор копирования.
\end{enumerate}
\item Инкапсуляция -- это (2)
\begin{enumerate}
\item архивирование проекта
\item сокрытие информации о классе
\item создание микросервисной архитектуры
\end{enumerate}
\item Наследуются от Object (3)
\begin{enumerate}
\item строки
\item потоки ввода-вывода
\item и то, и другое
\end{enumerate}
\item Является ли перегрузка полиморфизмом (2)
\begin{enumerate}
\item да, это истинный полиморфизм
\item да, это часть истинного полиморфизма
\item нет, это не полиморфизм
\end{enumerate}
\end{enumerate}
\end{itemize}
\subsubsection{Рассмотрение ДЗ}
\begin{itemize}
\item \textbf{Цель этапа:} Пояснить не очевидные моменты в формулировке ДЗ с лекции, синхронизировать прочитанный на лекции материал к началу семинара.
\item \textbf{Тайминг:} 15-20 минут.
\item \textbf{Действия преподавателя:}
\begin{itemize}
\item Преподаватель демонстрирует свой вариант решения домашнего задания из лекции;
\item возможно, по предварительному опросу, демонстрирует и разбирает вариант решения одного из студентов.
\end{itemize}
\item \textbf{Домашнее задание из лекции:}
\begin{itemize}
\item Написать класс кота так, чтобы каждому объекту кота присваивался личный порядковый целочисленный номер;
\textbf{Вариант решения в приложении \ref{appendix:hw1}}
\item Написать классы кота и собаки, наследники животного. У всех есть три действия: бежать, плыть, прыгать. Действия принимают размер препятствия и возвращают булев результат. Три ограничения: высота прыжка, расстояние, которое животное может пробежать, расстояние, которое животное может проплыть. Следует учесть, что коты не любят воду.
\textbf{Вариант решения в приложении \ref{appendix:hw2}}
\item Добавить механизм, создающий 25\% разброс значений каждого ограничения для каждого объекта.
\textbf{Вариант решения}
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Конструктор с вариативностью}]
Animal(String type, String name, float maxJump, float maxRun, float maxSwim) {
float jumpDiff = random.nextFloat() * maxJump - (maxJump / 2);
float runDiff = random.nextFloat() * maxRun - (maxRun / 2);
float swimDiff = random.nextFloat() * maxSwim - (maxSwim / 2);
this.type = type;
this.name = name;
this.maxJump = maxJump + jumpDiff;
this.maxRun = maxRun + runDiff;
this.maxSwim = maxSwim + swimDiff;
}
\end{lstlisting}
\end{itemize}
\end{itemize}
\subsubsection{Вопросы и ответы}
\begin{itemize}
\item \textbf{Ценность этапа} Вовлечение аудитории в обратную связь, пояснение неочевидных моментов в материале лекции и другой проделанной работе.
\item \textbf{Тайминг} 5-15 минут
\item \textbf{Действия преподавателя}
\begin{itemize}
\item Преподаватель ожидает вопросов по теме прошедшей лекции, викторины и продемонстрированной работы;
\item Если преподаватель затрудняется с ответом, необходимо мягко предложить студенту ответить на его вопрос на следующем семинаре (и не забыть найти ответ на вопрос студента!);
\item Предложить и показать пути самостоятельного поиска студентом ответа на заданный вопрос;
\item Посоветовать литературу на тему заданного вопроса;
\item Дополнительно указать на то, что все сведения для выполнения домашнего задания, прохождения викторины и работы на семинаре были рассмотрены в методическом материале к этому или предыдущим урокам.
\end{itemize}
\end{itemize}
\subsubsection{Задание 1}
\begin{itemize}
\item \textbf{Ценность этапа} Создание класса и объекта.
\item \textbf{Тайминг} 5 минут.
\item \textbf{Действия преподавателя}
\begin{itemize}
\item Первые пять минут уклоняться от ответов на уточняющие вопросы
\item Выдать задание студентам;
\end{itemize}
\item \textbf{Задания}:
\begin{itemize}
\item Создать класс "Сотрудник" с полями: ФИО, должность, телефон, зарплата, возраст;
\textbf{Вариант исполнения класса в приложении \ref{appendix:ct1}}
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Создание объекта класса}]
Employee employeeIvan = new Employee("Ivan", "Igorevich",
"Ovchinnikov", "8(495)000-11-22",
"developer", 50000, 1985);
\end{lstlisting}
\end{itemize}
\end{itemize}
\subsubsection{Задание 2}
\begin{itemize}
\item \textbf{Ценность этапа} Манипуляция информацией об объекте.
\item \textbf{Тайминг} 10 минут.
\item \textbf{Действия преподавателя}
\begin{itemize}
\item Пояснить студентам ценность этого опыта (отказ от вывода информации в терминал из сторонних объектов);
\item Пояснить студентам в каком виде выполнять и сдавать задания;
\item Выдать задание группам студентов;
\item Если группа студентов справилась с заданием, а времени осталось более 5 минут, выдавать группе задания «со звёздочкой».
\end{itemize}
\item \textbf{Задания}
\begin{itemize}
\item Написать функцию выводящую всю доступную информацию об объекте
\textbf{Вариант решения}
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Вывод информации об объекте в консоль}]
public void info() {
System.out.println("Employee{" +
"name='" + name + '\'' +
", midName='" + midName + '\'' +
", surName='" + surName + '\'' +
", position='" + position + '\'' +
", phone='" + phone + '\'' +
", salary=" + salary +
", age=" + getAge() +
'}');
}
\end{lstlisting}
\item [$*_1$] таким образом, чтобы функция возвращала значение;
\textbf{Вариант решения}
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Возврат информации об объекте}]
@Override
public String toString() {
return "Employee{" +
"name='" + name + '\'' +
", midName='" + midName + '\'' +
", surName='" + surName + '\'' +
", position='" + position + '\'' +
", phone='" + phone + '\'' +
", salary=" + salary +
", age=" + getAge() +
'}';
}
\end{lstlisting}
\item [$*_2$] с использованием форматирования строк.
\textbf{Вариант решения}
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Форматированная информация об объекте}]
@Override
public String toString() {
return String.format("Employee{" +
"name='%s', midName='%s', surName='%s'" +
", position='%s', phone='%s'" +
", salary=%d, age=%d}'",
name, midName, surName, position, phone, salary, getAge());
}
\end{lstlisting}
\end{itemize}
\end{itemize}
\subsubsection{Задание 3}
\begin{itemize}
\item \textbf{Ценность этапа} Создание и манипуляция множествами объектов.
\item \textbf{Тайминг} 20-25 минут.
\item \textbf{Действия преподавателя}
\begin{itemize}
\item Пояснить студентам ценность этого опыта (дополнительно напомнить, что классы создают для программы новый тип данных, а значит объектами можно пользоваться также, как и заранее созданными);
\item Пояснить студентам в каком виде выполнять и сдавать задания;
\item Выдать задание группам студентов;
\item Если группа студентов справилась с заданием, а времени осталось более 5 минут, выдавать группе задания «со звёздочкой».
\end{itemize}
\item \textbf{Задания}
\begin{itemize}
\item Создать массив из 5 сотрудников
\textbf{Вариант решения}
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Простой массив сотрудников}]
Employee ivan = new Employee("Ivan", "Igorevich",
"Ovchinnikov", "8(495)000-11-22",
"developer", 50000, 1985);
Employee andrey = new Employee("Andrey", "Viktorovich",
"Bezrukov", "8(495)111-22-33",
"fitter", 52000, 1973);
Employee evgeniy = new Employee("Evgeniy", "Viktorovich",
"Delfinov", "8(495)222-33-44",
"project manager", 40000, 1963);
Employee natalia = new Employee("Natalia", "Pavlovna",
"Keks", "8(495)333-44-55",
"senior developer", 90000, 1990);
Employee tatiana = new Employee("Tatiana", "Sergeevna",
"Krasotkina", "8(495)444-55-66",
"accountant", 50000, 1983);
Employee[] company = new Employee[5];
company[0] = ivan;
company[1] = andrey;
company[2] = evgeniy;
company[3] = natalia;
company[4] = tatiana;
\end{lstlisting}
\item [$*_1$] массив должен быть сразу инициализирован;
\textbf{Вариант решения}
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Инициализированный массив}]
Employee[] employees = { ivan, andrey, evgeniy, natalia, tatiana };
\end{lstlisting}
\item [$*_2$] массив должен быть сразу инициализирован и не должно быть создано дополнительных переменных.
\textbf{Вариант решения}
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Без дополнительных переменных}]
Employee[] employees = {
new Employee("Ivan", "Igorevich",
"Ovchinnikov", "8(495)000-11-22",
"developer", 50000, 1985),
new Employee("Andrey", "Viktorovich",
"Bezrukov", "8(495)111-22-33",
"fitter", 52000, 1973),
new Employee("Evgeniy", "Viktorovich",
"Delfinov", "8(495)222-33-44",
"project manager", 40000, 1963),
new Employee("Natalia", "Pavlovna",
"Keks", "8(495)333-44-55",
"senior developer", 90000, 1990),
new Employee("Tatiana", "Sergeevna",
"Krasotkina", "8(495)444-55-66",
"accountant", 50000, 1983)
};
\end{lstlisting}
\end{itemize}
\end{itemize}
\subsubsection{Задание 4}
\begin{itemize}
\item \textbf{Ценность этапа} Манипуляция информацией об объекте.
\item \textbf{Тайминг} 15-20 минут.
\item \textbf{Действия преподавателя}
\begin{itemize}
\item Пояснить студентам ценность этого опыта (часто возникают ситуации, когда необходимо осуществить фильтрацию данных или манипулировать только частью объектов. дополнительно указать на то, что часто методы, манипулирующие множеством объектов описывают внутри классов, но это не совсем верный подход с точки зрения архитектуры, и под такие методы желательно создавать отдельный класс, например, \code{EmployeeWorker});
\item Пояснить студентам в каком виде выполнять и сдавать задания;
\item Выдать задание группам студентов;
\item Если группа студентов справилась с заданием, а времени осталось более 5 минут, выдавать группе задания «со звёздочкой».
\end{itemize}
\item \textbf{Задания}
\begin{itemize}
\item Создать метод, повышающий зарплату всем сотрудникам старше 45 лет на 5000. Метод должен принимать в качестве параметра массив сотрудников.
\textbf{Вариант решения}
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Метод повышения зарплаты}]
// Employee
public void increaseSalary(int amount) {
this.salary += amount;
}
// Main
private static void increaser(Employee[] emp) {
for (int i = 0; i < emp.length; i++) {
if (emp[i].getAge() > 45) {
emp[i].increaseSalary(5000);
}
}
}
// main
for (int i = 0; i < employees.length; i++) {
increaser(employees);
}
\end{lstlisting}
\item [$*_1$] Написать тот же метод, но возраст и размер повышения должны быть параметрами метода.
\textbf{Вариант решения}
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Параметризированный метод повышения}]
// Main
private static void increaser(Employee[] emp, int age, int increment) {
for (int i = 0; i < emp.length; i++) {
if (emp[i].getAge() > age) {
emp[i].increaseSalary(increment);
}
}
}
// main
for (int i = 0; i < employees.length; i++) {
increaser(employees, 45, 5000);
}
\end{lstlisting}
\item [$*_2$] Написать тот же метод в качестве статического в классе сотрудника.
\textbf{Вариант решения}
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Статический метод и использование}]
// Employee
public static void increaser(Employee[] emp, int age, int increment) {
for (int i = 0; i < emp.length; i++) {
if (emp[i].getAge() > age) {
emp[i].increaseSalary(increment);
}
}
}
// main
for (int i = 0; i < employees.length; i++) {
Employee.increaser(employees, 45, 5000);
}
\end{lstlisting}
\end{itemize}
\end{itemize}
\subsubsection{Задание 5}
\begin{itemize}
\item \textbf{Ценность этапа} Соблюдение атомарности методов, независимость методов, манипулирующих данными от окружения.
\item \textbf{Тайминг} 10-15 минут.
\item \textbf{Действия преподавателя}
\begin{itemize}
\item Обратить внимание на то, что многие студенты пытаются объединить методы с похожими алгоритмами, но это неверный подход, нужно соблюдать атомарность методов. Важно, чтобы результаты работы не печатались в консоль, а возвращались из методов, чтобы код был переносимым;
\item Выдать задание группам студентов;
\item Если группа студентов справилась с заданием, а времени осталось более 5 минут, выдавать группе задания «со звёздочкой».
\end{itemize}
\item \textbf{Задания}
\begin{itemize}
\item Написать методы (принимающие на вход массив сотрудников), вычисляющие средний возраст и среднюю зарплату сотрудников, вывести результаты работы в консоль.
\textbf{Вариант решения}
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Методы подсчёта средних}]
private static float averageSalary(Employee[] emp) {
float result = 0;
for (int i = 0; i < emp.length; i++)
result += emp[i].getSalary();
return result / emp.length;
}
private static float averageAge(Employee[] emp){
float result = 0;
for (int i = 0; i < emp.length; i++)
result += emp[i].getAge();
return result / emp.length;
}
\end{lstlisting}
\end{itemize}
\subsubsection{Домашнее задание}
\begin{itemize}
\item \textbf{Ценность этапа} Задать задание для самостоятельного выполнения между занятиями.
\item \textbf{Тайминг} 5-10 минут.
\item \textbf{Действия преподавателя}
\begin{itemize}
\item Пояснить студентам в каком виде выполнять и сдавать задания
\item Уточнить кто будет проверять работы (преподаватель или ревьювер)
\item Объяснить к кому обращаться за помощью и где искать подсказки
\item Объяснить где взять проект заготовки для дз
\end{itemize}
\item \textbf{Задания}
\begin{enumerate}
\item [5-25 мин] Решить все задания (в том числе «со звёздочкой»), если они не были решены на семинаре, без ограничений по времени;
\textbf{Все варианты решения приведены в тексте семинара выше}
\item [5-10 мин] 1. Написать прототип компаратора - метод внутри класса сотрудника, сравнивающий две даты, представленные в виде трёх чисел гггг-мм-дд, без использования условного оператора.
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Сравнение возраста}]
//Employee
int bMonth;
int bDay;
/**
* returns
* negative integer if this object birthdate is less (earlier), than given (older)
* positive integer if this object birthdate is more (later), than given (younger)
* zero if this object is the same as given
* */
public int compare(int dd, int mm, int yyyy) {
//day = 0..30, 31 is binary 11111, ok to left shift month by 6
//month = 0..11, 15 is binary 1111, ok to left shift year by 5 more
int empl = bDay + (bMonth << 6) + (birth << 11);
int income = dd + (mm << 6) + (yyyy << 11);
return empl - income;
}
\end{lstlisting}
\item [10-15 мин] 2. Опишите класс руководителя, наследник от сотрудника. Перенесите статический метод повышения зарплаты в класс руководителя, модифицируйте метод таким образом, чтобы он мог поднять заработную плату всем, кроме руководителей. В основной программе создайте руководителя и поместите его в общий массив сотрудников. Повысьте зарплату всем сотрудникам и проследите, чтобы зарплата руководителя не повысилась.
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Менеджер - это тоже сотрудник}]
// Manager
package ru.gb.jcore;
public class Manager extends Employee {
public Manager(String name, String midName, String surName,
String phone, String position, int salary, int birth) {
super(name, midName, surName, phone, position, salary, birth);
}
public static void increaser(Employee[] emp, int age, int increment) {
for (int i = 0; i < emp.length; i++) {
if (emp[i].getAge() > age) {
if (!(emp[i] instanceof Manager))
emp[i].increaseSalary(increment);
}
}
}
}
\end{lstlisting}
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Более верное повышение зарплаты}]
// main
Employee[] employees = { ivan, andrey, evgeniy /*new Manager(...)*/, natalia, tatiana };
for (int i = 0; i < employees.length; i++) {
Manager.increaser(employees, 45, 5000);
}
\end{lstlisting}
\end{enumerate}
\end{itemize}
\end{itemize}
\subsubsection{Рефлексия и завершение семинара}
\begin{itemize}
\item \textbf{Цель этапа:} Привести урок к логическому завершению, посмотреть что студентам удалось, что было сложно и над чем нужно еще поработать
\item \textbf{Тайминг:} 5-10 минут
\item \textbf{Действия преподавателя:}
\begin{itemize}
\item Запросить обратную связь от студентов.
\item Подчеркните то, чему студенты научились на занятии.
\item Дайте рекомендации по решению заданий, если в этом есть необходимость
\item Дайте краткую обратную связь студентам.
\item Поделитесь ощущением от семинара.
\item Поблагодарите за проделанную работу.
\end{itemize}
\end{itemize}
\newpage
\appendix
\section*{Приложения}
\addcontentsline{toc}{section}{Приложения}
\renewcommand{\thesubsection}{\Asbuk{subsection}}
\subsection{Домашнее задание 1}
\label{appendix:hw1}
\lstinputlisting[language=Java,style=JCodeStyle,caption={Кот}]{src/s03-hw1-cat.java}
\subsection{Домашнее задание 2}
\label{appendix:hw2}
\lstinputlisting[language=Java,style=JCodeStyle,caption={Общий класс животного}]{src/s03-hw2-animal.java}
\lstinputlisting[language=Java,style=JCodeStyle,caption={Кот}]{src/s03-hw2-cat.java}
\lstinputlisting[language=Java,style=JCodeStyle,caption={Собака}]{src/s03-hw2-dog.java}
\lstinputlisting[language=Java,style=JCodeStyle,caption={Марафон}]{src/s03-hw2-marathon.java}
\subsection{Практическое задание 1}
\label{appendix:ct1}
\lstinputlisting[language=Java,style=JCodeStyle,caption={Сотрудник}]{src/s03-ct1-employee.java}
\end{document}

265
seminars/jtc4-04c.tex Normal file
View File

@ -0,0 +1,265 @@
\documentclass[../j-spec.tex]{subfiles}
\usepackage{spreadtab}
\begin{document}
\setcounter{section}{3}
\section{Семинар: обработка исключений}
\subsection{Инструментарий}
\begin{itemize}
\item \href{https://docs.google.com}{Презентация} для преподавателя, ведущего семинар;
\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.
\end{itemize}
\subsection{Цели семинара}
\begin{itemize}
\item Закрепить полученные на лекции знания об исключениях;
\item Попрактиковаться в написании собственных классов исключений;
\item Создание, выбрасывание и обработка исключений;
\item Обработка исключений в стиле «до захвата ресурса»;
\item Проброс исключений выше по стеку.
\end{itemize}
\subsection{План-содержание}
\noindent
\begin{spreadtab}{{longtable}{|p{37mm}|l|l|p{90mm}|}}
\hline
@ Что происходит & @ Время & @ Слайды & @ Описание \\
\hline
\endhead
@ Организационный момент & 5 tag(beg) & @ 1-5 & @ Преподаватель ожидает студентов, поддерживает активность и коммуникацию в чате, озвучиает цели и планы на семинар. Важно упомянуть, что выполнение домашних заданий с лекции является, фактически, подготовкой к семинару \\
\hline
@ Quiz & 10 & @ 6-18 & @ Преподаватель задаёт вопросы викторины, через 30 секунд демонстрирует слайд-подсказку и ожидает ответов (6 вопросов, по минуте на ответ) \\
\hline
@ Рассмотрение ДЗ лекции & 10 & @ 19-23 & @ Преподаватель демонстрирует свой вариант решения домашнего задания с лекции, возможно, по предварительному опросу, демонстрирует и разбирает вариант решения одного из студентов \\
\hline
@ Вопросы и ответы & 10 & @ 24 & @ Преподаватель ожидает вопросов по теме прошедшей лекции, викторины и продемонстрированной работы \\
\hline
@ Задание 1 & 30 & @ 25-28 & @ Сквозное задание, состоящее из объяснений в 6 пунктах, обязательных к исполнению. Всё задание выдаётся сразу целиком и является неделимым. \\
\hline
@ Перерыв (если нужен) & 5 & @ 33 & @ Преподаватель предлагает студентам перерыв на 5 минут (студенты голосуют) \\
\hline
@ Задание 2 & 30 & @ 29-32 & @ Сквозное задание, состоящее из объяснений в 6 пунктах, обязательных к исполнению. Всё задание выдаётся сразу целиком и является неделимым. \\
\hline
@ Домашнее задание & 5 & @ 45-46 & @ Объясните домашнее задание, подведите итоги урока \\
\hline
@ Рефлексия & 10 tag(end) & @ 47-48 & @ Преподаватель запрашивает обратную связь \\
\hline
@ Длительность & sum(cell(beg):cell(end)) & & \\
\hline
\end{spreadtab}
\subsection{Подробности}
\subsubsection{Организационный момент}
\begin{itemize}
\item \textbf{Цель этапа:} Позитивно начать урок, создать комфортную среду для обучения.
\item \textbf{Тайминг:} 3-5 минут.
\item \textbf{Действия преподавателя:}
\begin{itemize}
\item Запрашивает активность от аудитории в чате;
\item Презентует цели курса и семинара;
\item Презентует краткий план семинара и что студент научится делать.
\end{itemize}
\end{itemize}
\subsubsection{Quiz}
\begin{itemize}
\item \textbf{Цель этапа:} Вовлечение аудитории в обратную связь.
\item \textbf{Тайминг:} 5-7 минут (4 вопроса, по минуте на ответ).
\item \textbf{Действия преподавателя:}
\begin{itemize}
\item Преподаватель задаёт вопросы викторины, представленные на слайдах презентации;
\item через 30 секунд демонстрирует слайд-подсказку и ожидает ответов.
\end{itemize}
\item \textbf{Вопросы и ответы:}
\begin{enumerate}
\item
\begin{enumerate}
\item
\item
\item
\end{enumerate}
\item
\begin{enumerate}
\item
\item
\item
\end{enumerate}
\end{enumerate}
\end{itemize}
\subsubsection{Рассмотрение ДЗ}
\begin{itemize}
\item \textbf{Цель этапа:} Пояснить не очевидные моменты в формулировке ДЗ с лекции, синхронизировать прочитанный на лекции материал к началу семинара.
\item \textbf{Тайминг:} 15-20 минут.
\item \textbf{Действия преподавателя:}
\begin{itemize}
\item Преподаватель демонстрирует свой вариант решения домашнего задания из лекции;
\item возможно, по предварительному опросу, демонстрирует и разбирает вариант решения одного из студентов.
\end{itemize}
\item \textbf{Домашнее задание из лекции:}
\begin{itemize}
\item Напишите два наследника класса \code{Exception}: ошибка преобразования строки и ошибка преобразования столбца.
\textbf{Вариант решения}
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Конструктор с вариативностью}]
private static final class ColumnMismatchException extends RuntimeException {
ColumnMismatchException(String message) {
super("Columns exception: " + message);
}
}
private static final class NumberIsNotNumberException extends RuntimeException {
NumberIsNotNumberException(String message) {
super("Not a number found: " + message);
}
}
\end{lstlisting}
\item Разработайте исключения-наследники так, чтобы они информировали пользователя в формате ожидание/реальность.
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Конструктор с вариативностью}]
private static final class RowMismatchException extends RuntimeException {
RowMismatchException(int expected, int current, String value) {
super(String.format("Rows exception: expected %d rows. Received %d rows in '%s' string",
expected, current, value));
}
}
\end{lstlisting}
\item для проверки напишите программу, преобразующую квадратный массив целых чисел 5х5 в сумму чисел в этом массиве, при этом, программа должна выбросить исключение, если строк или столбцов в исходном массиве окажется не 5.
\textbf{Вариант решения представлен в приложении \ref{appendix:hw3}}
\end{itemize}
\end{itemize}
\subsubsection{Вопросы и ответы}
\begin{itemize}
\item \textbf{Ценность этапа} Задать задание для самостоятельного выполнения между занятиями.
\item \textbf{Тайминг} 5-15 минут
\item \textbf{Действия преподавателя}
\begin{itemize}
\item Преподаватель ожидает вопросов по теме прошедшей лекции, викторины и продемонстрированной работы;
\item Если преподаватель затрудняется с ответом, необходимо мягко предложить студенту ответить на его вопрос на следующем семинаре (и не забыть найти ответ на вопрос студента!);
\item Предложить и показать пути самостоятельного поиска студентом ответа на заданный вопрос;
\item Посоветовать литературу на тему заданного вопроса;
\item Дополнительно указать на то, что все сведения для выполнения домашнего задания, прохождения викторины и работы на семинаре были рассмотрены в методическом материале к этому или предыдущим урокам.
\end{itemize}
\end{itemize}
\subsubsection{Задание 1}
\begin{itemize}
\item \textbf{Ценность этапа} Написание почти полноценной механики по краткому ТЗ.
\item \textbf{Тайминг} 25-30 минут.
\item \textbf{Действия преподавателя}
\begin{itemize}
\item Выдать задание студентам;
\item Подробно объяснить, что именно требуется от студентов, избегая упоминания конкретных языковых конструкций.
\end{itemize}
\item \textbf{Задание}: Класс «Проверка логина и пароля».
\begin{enumerate}
\item Создать статический метод который принимает на вход три параметра: \code{login}, \code{password} и \code{confirmPassword}.
\item Длина \code{login} должна быть \textbf{меньше} 20 символов. Если \code{login} не соответствует этому требованию, необходимо выбросить \code{WrongLoginException}.
\item Длина \code{password} должна быть \textbf{не меньше} 20 символов. Также \code{password} и \code{confirmPassword} должны быть равны. Если \code{password} не соответствует этим требованиям, необходимо выбросить \code{WrongPasswordException}.
\item \code{WrongPasswordException} и \code{WrongLoginException} -- пользовательские классы исключения с двумя конструкторами - один по умолчанию, второй принимает параметры исключения (неверные данные) и возвращает пользователю в виде «ожидалось/фактически».
\item В основном классе программы необходимо по-разному обработать исключения.
\item Метод возвращает \code{true}, если значения верны или \code{false} в противном случае.
\end{enumerate}
\textbf{Вариант исполнения класса в приложении \ref{appendix:ct1}}
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Создание объекта класса}]
\end{lstlisting}
\end{itemize}
\subsubsection{Задание 2}
\begin{itemize}
\item \textbf{Ценность этапа} Написание наброска пет-проекта, повторение информации об ООП, работа с исключениями.
\item \textbf{Тайминг} 25-30 минут.
\item \textbf{Действия преподавателя}
\begin{itemize}
\item Выдать задание студентам;
\item Подробно объяснить, что именно требуется от студентов, избегая упоминания конкретных языковых конструкций.
\item обратить внимание на порядок обработки исключений, повторная попытка купить товар может производиться только тогда, когда остальные параметры покупки уже проверены.
\end{itemize}
\item \textbf{Задание}: Класс «Эмуляция интернет-магазина».
\begin{enumerate}
\item Написать классы покупатель (ФИО, возраст, телефон), товар (название, цена) и заказ (объект покупатель, объект товар, целочисленное количество).
\item Создать массив покупателей (инициализировать 2 элемента), массив товаров (инициализировать 5 элементов) и массив заказов (пустой на 5 элементов).
\item Создать статический метод «совершить покупку» со строковыми параметрами, соответствующими полям объекта заказа. Метод должен вернуть объект заказа.
\item Если в метод передан несуществующий покупатель -- метод должен выбросить исключение \code{CustomerException}, если передан несуществующий товар, метод должен выбросить исключение \code{ProductException}, если было передано отрицательное или слишком больше значение количества (например, 100), метод должен выбросить исключение \code{AmountException}.
\item Вызвать метод совершения покупки несколько раз таким образом, чтобы заполнить массив покупок возвращаемыми значениями. Обработать исключения следующим образом (в заданном порядке):
\begin{itemize}
\item если был передан неверный товар -- вывести в консоль сообщение об ошибке, не совершать данную покупку;
\item если было передано неверное количество -- купить товар в количестве 1;
\item если был передан неверный пользователь -- завершить работу приложения с исключением.
\end{itemize}
\item Вывести в консоль итоговое количество совершённых покупок после выполнения основного кода приложения.
\end{enumerate}
\textbf{Вариант исполнения класса в приложении \ref{appendix:ct1}}
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Создание объекта класса}]
\end{lstlisting}
\end{itemize}
\subsubsection{Домашнее задание}
\begin{itemize}
\item \textbf{Ценность этапа} Задать задание для самостоятельного выполнения между занятиями.
\item \textbf{Тайминг} 5-10 минут.
\item \textbf{Действия преподавателя}
\begin{itemize}
\item Пояснить студентам в каком виде выполнять и сдавать задания
\item Уточнить кто будет проверять работы (преподаватель или ревьювер)
\item Объяснить к кому обращаться за помощью и где искать подсказки
\item Объяснить где взять проект заготовки для дз
\end{itemize}
\item \textbf{Задания}
\begin{enumerate}
\item [5-25 мин] Решить все задания (в том числе «со звёздочкой»), если они не были решены на семинаре, без ограничений по времени;
\textbf{Все варианты решения приведены в тексте семинара выше}
\item [15 мин] 1. В класс покупателя добавить перечисление с гендерами, добавить в сотрудника свойство «пол» со значением созданного перечисления. Добавить геттеры, сеттеры.
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={}]
\end{lstlisting}
\item [20-25 мин] 2. Добавить в основную программу перечисление с праздниками (Новый Год, 8 марта, 23 февраля), написать метод, принимающий массив сотрудников, поздравляющий всех сотрудников с Новым Годом, женщин с 8 марта, а мужчин с 23 февраля.
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={}]
\end{lstlisting}
\end{enumerate}
\end{itemize}
\subsubsection{Рефлексия и завершение семинара}
\begin{itemize}
\item \textbf{Цель этапа:} Привести урок к логическому завершению, посмотреть что студентам удалось, что было сложно и над чем нужно еще поработать
\item \textbf{Тайминг:} 5-10 минут
\item \textbf{Действия преподавателя:}
\begin{itemize}
\item Запросить обратную связь от студентов.
\item Подчеркните то, чему студенты научились на занятии.
\item Дайте рекомендации по решению заданий, если в этом есть необходимость
\item Дайте краткую обратную связь студентам.
\item Поделитесь ощущением от семинара.
\item Поблагодарите за проделанную работу.
\end{itemize}
\end{itemize}
\newpage
\appendix
\section*{Приложения}
\addcontentsline{toc}{section}{Приложения}
\renewcommand{\thesubsection}{\Asbuk{subsection}}
\subsection{Домашнее задание 3}
\label{appendix:hw3}
\lstinputlisting[language=Java,style=JCodeStyle,caption={Основная программа}]{src/s04-hw3-exceptional.java}
\subsection{Практическое задание 1}
\label{appendix:ct1}
\lstinputlisting[language=Java,style=JCodeStyle,caption={Логин}]{src/s04-ct1-sign.java}
\subsection{Практическое задание 2}
\label{appendix:ct2}
\lstinputlisting[language=Java,style=JCodeStyle,caption={Магазин}]{src/s04-ct2-shop.java}
\end{document}

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 374 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 234 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 255 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@ -0,0 +1,22 @@
package ru.gb.jcore.regular;
/**
* <@\lh{dkgreen}{Декоратор. Он декорирует, то есть, накладывает на результат декорации.}@>
* <@\lh{dkgreen}{Внешний вид важен, поэтому этот класс существует.}@>
* */
public class Decorator {
/**
* <@\lh{dkgreen}{Функция декорирования числа для вывода в консоль}@>
* <@\lh{dkgreen}{в виде строки с преамбулой 'Вот Ваше число'}@>
*
* @param a <@\lh{dkgreen}{число, требующее декорации}@>
* @return <@\lh{dkgreen}{Отформатированная строка.}@>
* */
public static String decorate(int a) {
/*
* <@\lh{dkgreen}{Метод декорирует число, добавляя к нему строку}@>
* <@\lh{dkgreen}{при помощи функции форматирования строк}@>
* */
return String.format("Here is your number: %d.", a);
}
}

View File

@ -0,0 +1,26 @@
package ru.gb.jcore.sample;
import ru.gb.jcore.regular.Decorator;
import ru.gb.jcore.regular.OtherClass;
/**
* <@\lh{dkgreen}{Основной класс приложения. Здесь мы можем описать}@>
* <@\lh{dkgreen}{его основное назначение и способы взаимодействия с ним.}@>
* */
public class Main {
/**
* <@\lh{dkgreen}{Точка входа в программу. С неё всегда всё начинается.}@>
*
* @param args <@\lh{dkgreen}{стандартные аргументы командной строки}@>
* */
public static void main(String[] args) {
int result = OtherClass.add(2, 2);
System.out.println(Decorator.decorate(result));
result = OtherClass.sub(2, 2);
System.out.println(Decorator.decorate(result));
result = OtherClass.mul(2, 2);
System.out.println(Decorator.decorate(result));
result = OtherClass.div(2, 2);
System.out.println(Decorator.decorate(result));
}
}

View File

@ -0,0 +1,51 @@
package ru.gb.jcore.regular;
/**
* <@\lh{dkgreen}{Другой, очень полезный класс приложения. Здесь мы можем описать}@>
* <@\lh{dkgreen}{его основное назначение и способы взаимодействия с ним.}@>
* */
public class OtherClass {
/**
* <@\lh{dkgreen}{Функция суммирования двух целых чисел}@>
*
* @param a <@\lh{dkgreen}{первое слагаемое}@>
* @param b <@\lh{dkgreen}{второе слагаемое}@>
* @return <@\lh{dkgreen}{сумма a и b, без проверки на переполнение переменной.}@>
* */
public static int add(int a, int b) {
return a + b; // <@\lh{dkgreen}{возврат без проверки переполнения}@>
}
/**
* <@\lh{dkgreen}{Функция деления двух целых чисел}@>
*
* @param a <@\lh{dkgreen}{делимое}@>
* @param b <@\lh{dkgreen}{делитель}@>
* @return <@\lh{dkgreen}{частное a и b, без проверки на переполнение переменной.}@>
* */
public static int div(int a, int b) {
return a / b; // <@\lh{dkgreen}{возврат без проверки переполнения}@>
}
/**
* <@\lh{dkgreen}{Функция умножения двух целых чисел}@>
*
* @param a <@\lh{dkgreen}{первый множитель}@>
* @param b <@\lh{dkgreen}{второй множитель}@>
* @return <@\lh{dkgreen}{произведение a и b, без проверки на переполнение переменной.}@>
* */
public static int mul(int a, int b) {
return a * b; // <@\lh{dkgreen}{возврат без проверки переполнения}@>
}
/**
* <@\lh{dkgreen}{Функция вычитания двух целых чисел}@>
*
* @param a <@\lh{dkgreen}{уменьшаемое}@>
* @param b <@\lh{dkgreen}{вычитаемое}@>
* @return <@\lh{dkgreen}{разность a и b, без проверки на переполнение переменной.}@>
* */
public static int sub(int a, int b) {
return a - b; // <@\lh{dkgreen}{возврат без проверки переполнения}@>
}
}

View File

@ -0,0 +1,24 @@
SRC_DIR := src
OUT_DIR := out
DOC_DIR := doc
JC := javac
JDOC := javadoc
JSRC := -sourcepath ./$(SRC_DIR)
JCLASS := -cp ./$(OUT_DIR)
JCDEST := -d $(OUT_DIR)
JDOCDEST := -d $(DOC_DIR)
MAIN_SOURCE := ru/gb/jcore/sample/Main
MAIN_CLASS := ru.gb.jcore.sample.Main
all:
${JC} ${JSRC} ${JCDEST} ${SRC_DIR}/${MAIN_SOURCE}.java
clean:
rm -R ${OUT_DIR}
run:
cd out && java ${MAIN_CLASS}
docs:
${JDOC}) ${JDOCDEST} ${JSRC} ${JCLASS} -subpackages ru

View File

@ -0,0 +1,7 @@
services:
app:
image: bellsoft/liberica-openjdk-alpine:11.0.16.1-1
command: javac -sourcepath /app/src -d /app/out /app/src/ru/gb/jcore/sample/Main.java
volumes:
- ./bin:/app/out
- ./src:/app/src

View File

@ -0,0 +1,6 @@
services:
app:
image: bellsoft/liberica-openjdk-alpine:11.0.16.1-1
command: java -classpath /app/out ru.gb.jcore.sample.Main
volumes:
- ./bin:/app/out

View File

@ -0,0 +1,8 @@
services:
app:
image: bellsoft/liberica-openjdk-alpine:11.0.16.1-1
command: javadoc -sourcepath /app/src -cp /app/out -d /app/doc -subpackages ru
volumes:
- ./bin:/app/out
- ./src:/app/src
- ./doc:/app/doc

View File

@ -0,0 +1,15 @@
package ru.bg;
/**
* <@\lh{dkgreen}{Это уже весьма усложнённый класс, мы будем его вызывать из простого}@>
*/
public class Complex {
/**
* <@\lh{dkgreen}{Функция, возвращающая какую-то строку. Возможно, даже приветствующую мир.}@>
*
* @return <@\lh{dkgreen}{строка с приветствием.}@>
* */
public static String hello() {
return "Hello, world!";
}
}

View File

@ -0,0 +1,17 @@
package ru.gb;
import ru.bg.Complex;
/**
* <@\lh{dkgreen}{Это простой класс. Он простой настолько, что ничего не делает}@>
*/
public class Simple {
/**
* <@\lh{dkgreen}{Функция запускающая программу и приветствующая мир.}@>
* <@\lh{dkgreen}{Наверное, самая популярная функция в мире.}@>
*
* @param args <@\lh{dkgreen}{стандартные аргументы командной строки}@>
* */
public static void main(String[] args) {
System.out.println(Complex.hello());
}
}

View File

@ -0,0 +1,11 @@
private static String caesar(String in, int key, boolean encrypt) {
if (in == null || in.isEmpty())
return null;
final int len = in.length();
char[] out = new char[len];
for (int i = 0; i < len; ++i) {
out[i] = (char) (in.charAt(i) + ((encrypt) ? key : -key));
}
return new String(out);
}

View File

@ -0,0 +1,11 @@
private static void shifter(int[] a, int n) {
n %= a.length;
int shift = a.length + n;
shift %= a.length;
for (int i = 0; i < shift; i++) {
int temp = a[a.length - 1];
System.arraycopy(a, 0, a, 1, a.length - 1);
a[0] = temp;
}
}

View File

@ -0,0 +1,7 @@
private static void change(int[] a) {
for (int i = 0; i < a.length; i++) {
a[i] = 1 - a[i];
// a[i] = (a[i] - 1) * -1;
// a[i] = (a[i] + 1) % 2;
}
}

View File

@ -0,0 +1,9 @@
int countEvens(int[] arr) {
int counter = 0;
for (int i = 0; i < arr.length; ++i) {
if (arr[i] % 2 == 0) {
counter++;
}
}
return counter;
}

View File

@ -0,0 +1,9 @@
int spread(int[] arr) {
int min = arr[0];
int max = arr[0];
for (int i = 1; i < arr.length; ++i) {
if (arr[i] < min) min = arr[i];
if (arr[i] > max) max = arr[i];
}
return max - min;
}

View File

@ -0,0 +1,7 @@
boolean zero2(int[] arr) {
for (int i = 0; i < arr.length - 1; ++i) {
if (arr[i] == 0 && arr[i + 1] == 0)
return true;
}
return false;
}

View File

@ -0,0 +1,64 @@
package ru.gb.jcore;
public class Employee {
private static final int CURRENT_YEAR = 2022;
String name;
String midName;
String surName;
String position;
String phone;
int salary;
int birth;
public Employee(String name, String midName, String surName,
String phone, String position, int salary, int birth) {
this.name = name;
this.midName = midName;
this.surName = surName;
this.position = position;
this.phone = phone;
this.salary = salary;
this.birth = birth;
}
public String getName() {
return name;
}
public String getMidName() {
return midName;
}
public String getSurName() {
return surName;
}
public String getPosition() {
return position;
}
public void setPosition(String position) {
this.position = position;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
public int getAge() {
return CURRENT_YEAR - birth;
}
}

View File

@ -0,0 +1,33 @@
package ru.gb.jcore;
public class Cat {
private static final int CURRENT_YEAR = 2022;
private static int id = 0;
private String name;
private String color;
private int birthYear;
public int uid;
Cat (String name, String color, int age) {
setBirth(age);
this.name = name;
this.color = color;
this.uid = ++id;
}
private void setBirth(int age) {
this.birthYear = CURRENT_YEAR - age;
}
public int getUid() {
return uid;
}
public String getColor() {
return color;
}
public int getAge() {
return CURRENT_YEAR - birthYear;
}
public String getName() {
return name;
}
}

View File

@ -0,0 +1,50 @@
package ru.gb.jcore.marathon;
import java.util.Random;
public abstract class Animal {
static final int SWIM_FAIL = 0;
static final int SWIM_OK = 1;
static final int SWIM_WTF = -1;
private String type;
private String name;
private float maxRun;
private float maxSwim;
private float maxJump;
private final Random random = new Random();
Animal(String type, String name, float maxJump, float maxRun, float maxSwim) {
this.type = type;
this.name = name;
this.maxJump = maxJump;
this.maxRun = maxRun;
this.maxSwim = maxSwim;
}
String getName() {
return this.name;
}
String getType() {
return this.type;
}
float getMaxRun() {
return this.maxRun;
}
float getMaxSwim() {
return this.maxSwim;
}
float getMaxJump() {
return this.maxJump;
}
protected boolean run(float distance) {
return (distance <= maxRun);
}
protected int swim(float distance) {
return (distance <= maxSwim) ? SWIM_OK : SWIM_FAIL;
}
protected boolean jump(float height) {
return (height <= maxJump);
}
}

View File

@ -0,0 +1,13 @@
package ru.gb.jcore.marathon;
public class Cat extends Animal {
Cat(String name) {
super("Cat", name, 2, 200, 1);
}
@Override
protected int swim(float distance) {
return Animal.SWIM_WTF;
}
}

View File

@ -0,0 +1,9 @@
package ru.gb.jcore.marathon;
class Dog extends Animal {
Dog(String name, float maxJump, float maxRun, float maxSwim) {
super("Dog", name, maxJump, maxRun, maxSwim);
}
}

View File

@ -0,0 +1,35 @@
package ru.gb.jcore.marathon;
public class Marathon {
public static void main(String[] args) {
Cat c = new Cat("Barseek");
Cat c0 = new Cat("Moorzeek");
Dog d = new Dog("Toozeek", 0.5f, 500, 10);
Dog d0 = new Dog("Shaareek", 0.5f, 500, 10);
Animal[] arr = {c, c0, d, d0};
float toJump = 1.5f;
float toRun = 350;
float toSwim = 5;
for (int i = 0; i < arr.length; i++) {
String nameString = arr[i].getType() + " " + arr[i].getName() + " can ";
String eventName = String.format("jump max %.2fm. Tries to jump ", arr[i].getMaxJump());
String eventResult = (arr[i].jump(toJump)) ? "succeed" : "fails";
System.out.println(nameString + eventName + toJump + "m and " + eventResult);
eventName = String.format("run max %.2fm. Tries to run ", arr[i].getMaxRun());
eventResult = arr[i].run(toRun) ? "succeed" : "fails";
System.out.println(nameString + eventName + toRun + "m and " + eventResult);
int swimResult = arr[i].swim(toSwim);
eventName = String.format("swim max %.2fm. Tries to swim ", arr[i].getMaxSwim());
eventResult = (swimResult == Animal.SWIM_OK) ? "succeed" : "fails";
if (swimResult == Animal.SWIM_WTF)
eventResult = "too scared to enter the water";
System.out.println(nameString + eventName + toSwim + "m and " + eventResult);
}
}
}

View File

@ -0,0 +1,79 @@
package ru.gb.jcore;
import java.util.Arrays;
public class Exceptional {
private static final class ColumnMismatchException extends RuntimeException {
ColumnMismatchException(String message) {
super("Columns exception: " + message);
}
}
private static final class NumberIsNotNumberException extends RuntimeException {
NumberIsNotNumberException(String message) {
super("Not a number found: " + message);
}
}
private static final class RowMismatchException extends RuntimeException {
RowMismatchException(int expected, int current, String value) {
super(String.format("Rows exception: expected %d rows. Received %d rows in '%s' string",
expected, current, value));
}
}
private static final String CORRECT_STRING= "1 3 1 2\n2 3 2 2\n5 6 7 1\n3 3 1 0";
private static final String EXTRA_ROW_STRING= "1 3 1 2\n2 3 2 2\n5 6 7 1\n3 3 1 0\n1 2 3 4";
private static final String EXTRA_COL_STRING= "1 3 1 2 1\n2 3 2 2 1\n5 6 7 1 1\n3 3 1 0 1";
private static final String NO_ROW_STRING= "1 3 1 2\n2 3 2 2\n5 6 7 1";
private static final String NO_COL_STRING= "1 3 1 2\n2 3 2 2\n5 6 7 1\n3 3 1";
private static final String HAS_CHAR_STRING= "1 3 1 2\n2 3 2 2\n5 6 7 1\n3 3 1 A";
private static final int MATRIX_ROWS= 4;
private static final int MATRIX_COLS= 4;
private static String[][] stringToMatrix(String value) {
String[] rows = value.split("\n");
if (rows.length !=MATRIX_ROWS)
throw new RowMismatchException(MATRIX_ROWS, rows.length, value);
String[][] result = new String[MATRIX_ROWS][];
for (int i = 0; i < result.length; i++) {
result[i] = rows[i].split(" ");
if (result[i].length !=MATRIX_COLS)
throw new ColumnMismatchException(result[i].length + ":\n" + value);
}
return result;
}
private static float calcMatrix(String[][] matrix) {
float result = 0;
int len = 0;
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
try {
result += Integer.parseInt(matrix[i][j]);
++len;
} catch (NumberFormatException e) {
throw new NumberIsNotNumberException(matrix[i][j]);
}
}
}
return result / len;
}
public static void main(String[] args) {
try {
// final String[][] matrix = stringToMatrix(CORRECT_STRING);
// final String[][] matrix = stringToMatrix(NO_ROW_STRING);
// final String[][] matrix = stringToMatrix(NO_COL_STRING);
final String[][] matrix =stringToMatrix(HAS_CHAR_STRING);
System.out.println(Arrays.deepToString(matrix));
System.out.println("Half sum = " +calcMatrix(matrix));
} catch (NumberIsNotNumberException exceptionObjectName) {
System.out.println("A NumberFormatException is thrown: " + exceptionObjectName.getMessage());
} catch (RowMismatchException | ColumnMismatchException superExceptionName) {
System.out.println("A RuntimeException successor is thrown: " + superExceptionName.getMessage());
}
}
}

View File

@ -19,6 +19,7 @@
\usepackage{booktabs}% http://ctan.org/pkg/booktabs
\usepackage{setspace,fontspec}
\usepackage{amsmath}
\usepackage{spreadtab}
\usepackage{svg}
\newcommand{\tabitem}{~~\llap{\textbullet}~~}
@ -58,9 +59,9 @@
\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}
\cfoot{\faRocket}
% \rfoot{Всего слов: \wordcount}
}

View File

@ -1,4 +1,4 @@
%% Creator: Inkscape 1.2.1 (9c6d41e4, 2022-07-14), www.inkscape.org
%% Creator: Inkscape inkscape 0.92.4, www.inkscape.org
%% PDF/EPS/PS + LaTeX output extension by Johan Engelen, 2010
%% Accompanies image file 'jc-02-float-struct32_svg-tex.pdf' (pdf, eps, ps)
%%

View File

@ -1,4 +1,4 @@
%% Creator: Inkscape 1.2.1 (9c6d41e4, 2022-07-14), www.inkscape.org
%% Creator: Inkscape inkscape 0.92.4, www.inkscape.org
%% PDF/EPS/PS + LaTeX output extension by Johan Engelen, 2010
%% Accompanies image file 'jc-02-float-struct_svg-tex.pdf' (pdf, eps, ps)
%%

Binary file not shown.

View File

@ -0,0 +1,65 @@
%% Creator: Inkscape inkscape 0.92.4, www.inkscape.org
%% PDF/EPS/PS + LaTeX output extension by Johan Engelen, 2010
%% Accompanies image file 'jc-03-class-obj-fields_svg-tex.pdf' (pdf, eps, ps)
%%
%% To include the image in your LaTeX document, write
%% \input{<filename>.pdf_tex}
%% instead of
%% \includegraphics{<filename>.pdf}
%% To scale the image, write
%% \def\svgwidth{<desired width>}
%% \input{<filename>.pdf_tex}
%% instead of
%% \includegraphics[width=<desired width>]{<filename>.pdf}
%%
%% Images with a different path to the parent latex file can
%% be accessed with the `import' package (which may need to be
%% installed) using
%% \usepackage{import}
%% in the preamble, and then including the image with
%% \import{<path to file>}{<filename>.pdf_tex}
%% Alternatively, one can specify
%% \graphicspath{{<path to file>/}}
%%
%% For more information, please see info/svg-inkscape on CTAN:
%% http://tug.ctan.org/tex-archive/info/svg-inkscape
%%
\begingroup%
\makeatletter%
\providecommand\color[2][]{%
\errmessage{(Inkscape) Color is used for the text in Inkscape, but the package 'color.sty' is not loaded}%
\renewcommand\color[2][]{}%
}%
\providecommand\transparent[1]{%
\errmessage{(Inkscape) Transparency is used (non-zero) for the text in Inkscape, but the package 'transparent.sty' is not loaded}%
\renewcommand\transparent[1]{}%
}%
\providecommand\rotatebox[2]{#2}%
\newcommand*\fsize{\dimexpr\f@size pt\relax}%
\newcommand*\lineheight[1]{\fontsize{\fsize}{#1\fsize}\selectfont}%
\ifx\svgwidth\undefined%
\setlength{\unitlength}{237.00155419bp}%
\ifx\svgscale\undefined%
\relax%
\else%
\setlength{\unitlength}{\unitlength * \real{\svgscale}}%
\fi%
\else%
\setlength{\unitlength}{\svgwidth}%
\fi%
\global\let\svgwidth\undefined%
\global\let\svgscale\undefined%
\makeatother%
\begin{picture}(1,0.44620459)%
\lineheight{1}%
\setlength\tabcolsep{0pt}%
\put(0.17332677,0.38199245){\color[rgb]{0,0,0}\makebox(0,0)[lt]{\lineheight{1.25}\smash{\begin{tabular}[t]{l}class\end{tabular}}}}%
\put(0.01740745,0.28639306){\color[rgb]{0,0,0}\makebox(0,0)[lt]{\lineheight{1.25}\smash{\begin{tabular}[t]{l}fields\end{tabular}}}}%
\put(0,0){\includegraphics[width=\unitlength,page=1]{jc-03-class-obj-fields_svg-tex.pdf}}%
\put(0.72942805,0.34968375){\makebox(0,0)[lt]{\lineheight{1.25}\smash{\begin{tabular}[t]{l}object1\end{tabular}}}}%
\put(0.66613736,0.28639297){\makebox(0,0)[lt]{\lineheight{1.25}\smash{\begin{tabular}[t]{l}field values\end{tabular}}}}%
\put(0.72942805,0.12816619){\makebox(0,0)[lt]{\lineheight{1.25}\smash{\begin{tabular}[t]{l}object2\end{tabular}}}}%
\put(0.66613736,0.0648754){\makebox(0,0)[lt]{\lineheight{1.25}\smash{\begin{tabular}[t]{l}field values\end{tabular}}}}%
\put(0,0){\includegraphics[width=\unitlength,page=2]{jc-03-class-obj-fields_svg-tex.pdf}}%
\end{picture}%
\endgroup%

Binary file not shown.

View File

@ -0,0 +1,69 @@
%% Creator: Inkscape inkscape 0.92.4, www.inkscape.org
%% PDF/EPS/PS + LaTeX output extension by Johan Engelen, 2010
%% Accompanies image file 'jc-03-class-obj-full_svg-tex.pdf' (pdf, eps, ps)
%%
%% To include the image in your LaTeX document, write
%% \input{<filename>.pdf_tex}
%% instead of
%% \includegraphics{<filename>.pdf}
%% To scale the image, write
%% \def\svgwidth{<desired width>}
%% \input{<filename>.pdf_tex}
%% instead of
%% \includegraphics[width=<desired width>]{<filename>.pdf}
%%
%% Images with a different path to the parent latex file can
%% be accessed with the `import' package (which may need to be
%% installed) using
%% \usepackage{import}
%% in the preamble, and then including the image with
%% \import{<path to file>}{<filename>.pdf_tex}
%% Alternatively, one can specify
%% \graphicspath{{<path to file>/}}
%%
%% For more information, please see info/svg-inkscape on CTAN:
%% http://tug.ctan.org/tex-archive/info/svg-inkscape
%%
\begingroup%
\makeatletter%
\providecommand\color[2][]{%
\errmessage{(Inkscape) Color is used for the text in Inkscape, but the package 'color.sty' is not loaded}%
\renewcommand\color[2][]{}%
}%
\providecommand\transparent[1]{%
\errmessage{(Inkscape) Transparency is used (non-zero) for the text in Inkscape, but the package 'transparent.sty' is not loaded}%
\renewcommand\transparent[1]{}%
}%
\providecommand\rotatebox[2]{#2}%
\newcommand*\fsize{\dimexpr\f@size pt\relax}%
\newcommand*\lineheight[1]{\fontsize{\fsize}{#1\fsize}\selectfont}%
\ifx\svgwidth\undefined%
\setlength{\unitlength}{237.00155419bp}%
\ifx\svgscale\undefined%
\relax%
\else%
\setlength{\unitlength}{\unitlength * \real{\svgscale}}%
\fi%
\else%
\setlength{\unitlength}{\svgwidth}%
\fi%
\global\let\svgwidth\undefined%
\global\let\svgscale\undefined%
\makeatother%
\begin{picture}(1,0.44620459)%
\lineheight{1}%
\setlength\tabcolsep{0pt}%
\put(0.17332677,0.38199245){\makebox(0,0)[lt]{\lineheight{1.25}\smash{\begin{tabular}[t]{l}class\end{tabular}}}}%
\put(0.01740745,0.28639306){\makebox(0,0)[lt]{\lineheight{1.25}\smash{\begin{tabular}[t]{l}fields\end{tabular}}}}%
\put(0.01740745,0.22310236){\makebox(0,0)[lt]{\lineheight{1.25}\smash{\begin{tabular}[t]{l}methods\end{tabular}}}}%
\put(0.01740745,0.15981167){\makebox(0,0)[lt]{\lineheight{1.25}\smash{\begin{tabular}[t]{l}static fields\end{tabular}}}}%
\put(0.01740745,0.09652089){\makebox(0,0)[lt]{\lineheight{1.25}\smash{\begin{tabular}[t]{l}static methods\end{tabular}}}}%
\put(0.01740745,0.03323019){\makebox(0,0)[lt]{\lineheight{1.25}\smash{\begin{tabular}[t]{l}static field values\end{tabular}}}}%
\put(0,0){\includegraphics[width=\unitlength,page=1]{jc-03-class-obj-full_svg-tex.pdf}}%
\put(0.72942805,0.34968375){\makebox(0,0)[lt]{\lineheight{1.25}\smash{\begin{tabular}[t]{l}object1\end{tabular}}}}%
\put(0.66613736,0.28639297){\makebox(0,0)[lt]{\lineheight{1.25}\smash{\begin{tabular}[t]{l}field values\end{tabular}}}}%
\put(0.72942805,0.12816619){\makebox(0,0)[lt]{\lineheight{1.25}\smash{\begin{tabular}[t]{l}object2\end{tabular}}}}%
\put(0.66613736,0.0648754){\makebox(0,0)[lt]{\lineheight{1.25}\smash{\begin{tabular}[t]{l}field values\end{tabular}}}}%
\put(0,0){\includegraphics[width=\unitlength,page=2]{jc-03-class-obj-full_svg-tex.pdf}}%
\end{picture}%
\endgroup%

Binary file not shown.

View File

@ -0,0 +1,66 @@
%% Creator: Inkscape inkscape 0.92.4, www.inkscape.org
%% PDF/EPS/PS + LaTeX output extension by Johan Engelen, 2010
%% Accompanies image file 'jc-03-class-obj-nostatic_svg-tex.pdf' (pdf, eps, ps)
%%
%% To include the image in your LaTeX document, write
%% \input{<filename>.pdf_tex}
%% instead of
%% \includegraphics{<filename>.pdf}
%% To scale the image, write
%% \def\svgwidth{<desired width>}
%% \input{<filename>.pdf_tex}
%% instead of
%% \includegraphics[width=<desired width>]{<filename>.pdf}
%%
%% Images with a different path to the parent latex file can
%% be accessed with the `import' package (which may need to be
%% installed) using
%% \usepackage{import}
%% in the preamble, and then including the image with
%% \import{<path to file>}{<filename>.pdf_tex}
%% Alternatively, one can specify
%% \graphicspath{{<path to file>/}}
%%
%% For more information, please see info/svg-inkscape on CTAN:
%% http://tug.ctan.org/tex-archive/info/svg-inkscape
%%
\begingroup%
\makeatletter%
\providecommand\color[2][]{%
\errmessage{(Inkscape) Color is used for the text in Inkscape, but the package 'color.sty' is not loaded}%
\renewcommand\color[2][]{}%
}%
\providecommand\transparent[1]{%
\errmessage{(Inkscape) Transparency is used (non-zero) for the text in Inkscape, but the package 'transparent.sty' is not loaded}%
\renewcommand\transparent[1]{}%
}%
\providecommand\rotatebox[2]{#2}%
\newcommand*\fsize{\dimexpr\f@size pt\relax}%
\newcommand*\lineheight[1]{\fontsize{\fsize}{#1\fsize}\selectfont}%
\ifx\svgwidth\undefined%
\setlength{\unitlength}{237.00155419bp}%
\ifx\svgscale\undefined%
\relax%
\else%
\setlength{\unitlength}{\unitlength * \real{\svgscale}}%
\fi%
\else%
\setlength{\unitlength}{\svgwidth}%
\fi%
\global\let\svgwidth\undefined%
\global\let\svgscale\undefined%
\makeatother%
\begin{picture}(1,0.44620459)%
\lineheight{1}%
\setlength\tabcolsep{0pt}%
\put(0.17332677,0.38199245){\makebox(0,0)[lt]{\lineheight{1.25}\smash{\begin{tabular}[t]{l}class\end{tabular}}}}%
\put(0.01740745,0.28639306){\makebox(0,0)[lt]{\lineheight{1.25}\smash{\begin{tabular}[t]{l}fields\end{tabular}}}}%
\put(0.01740745,0.22310236){\makebox(0,0)[lt]{\lineheight{1.25}\smash{\begin{tabular}[t]{l}methods\end{tabular}}}}%
\put(0,0){\includegraphics[width=\unitlength,page=1]{jc-03-class-obj-nostatic_svg-tex.pdf}}%
\put(0.72942805,0.34968375){\makebox(0,0)[lt]{\lineheight{1.25}\smash{\begin{tabular}[t]{l}object1\end{tabular}}}}%
\put(0.66613736,0.28639297){\makebox(0,0)[lt]{\lineheight{1.25}\smash{\begin{tabular}[t]{l}field values\end{tabular}}}}%
\put(0.72942805,0.12816619){\makebox(0,0)[lt]{\lineheight{1.25}\smash{\begin{tabular}[t]{l}object2\end{tabular}}}}%
\put(0.66613736,0.0648754){\makebox(0,0)[lt]{\lineheight{1.25}\smash{\begin{tabular}[t]{l}field values\end{tabular}}}}%
\put(0,0){\includegraphics[width=\unitlength,page=2]{jc-03-class-obj-nostatic_svg-tex.pdf}}%
\end{picture}%
\endgroup%