0% нашли этот документ полезным (0 голосов)
40 просмотров175 страниц

Java Theory

Документ содержит информацию о современных технологиях программирования на языке Java, включая платформу Java Development Kit (JDK), Java Virtual Machine (JVM), JIT-компилятор, системы сборки проектов, типы данных, переменные, комментарии и операции языка Java. Описаны ключевые компоненты JDK, функции и принципы работы JVM и JIT-компилятора, а также структура проекта в Apache Maven. Также рассматриваются примитивные и ссылочные типы данных, области видимости переменных, спецификаторы доступа и различные виды комментариев.
Авторское право
© © All Rights Reserved
Мы серьезно относимся к защите прав на контент. Если вы подозреваете, что это ваш контент, заявите об этом здесь.
0% нашли этот документ полезным (0 голосов)
40 просмотров175 страниц

Java Theory

Документ содержит информацию о современных технологиях программирования на языке Java, включая платформу Java Development Kit (JDK), Java Virtual Machine (JVM), JIT-компилятор, системы сборки проектов, типы данных, переменные, комментарии и операции языка Java. Описаны ключевые компоненты JDK, функции и принципы работы JVM и JIT-компилятора, а также структура проекта в Apache Maven. Также рассматриваются примитивные и ссылочные типы данных, области видимости переменных, спецификаторы доступа и различные виды комментариев.
Авторское право
© © All Rights Reserved
Мы серьезно относимся к защите прав на контент. Если вы подозреваете, что это ваш контент, заявите об этом здесь.
Вы находитесь на странице: 1/ 175

Список вопросов и задач для экзамена по дисциплине «Современные

технологии программирования»
1.​ Платформа Java: Java Development Kit (JDK): состав, назначение.
Кроссплатформенность языка Java.
Java Development Kit (JDK) - это набор сервисов, облегчающих процесс
написания кода на языке Java. Инструменты JDK нужны для написания кода,
его компиляции, отлаживания и запуска. Он не содержит никаких текстовых
редакторов, а оперирует только уже существующими Java -файлами.

Пакет JDK состоит из:


●​ Java Runtime Environment (JRE)
Среда выполнения работает поверх операционной системы
компьютера. JDK JRE отвечает за объединение кода Java с
библиотеками. Затем она создает экземпляр JVM, в котором
выполняется программа.
●​ интерпретатор (Java)
●​ компилятор (javac)
Компилятор делает из начального кода байт-версию. Полученный
вариант может работать на любой платформе с JVM.Для компилятора
работает принцип «напиши один раз, применяй где угодно».
●​ архиватор (jar)
●​ автоматическая документация (javadoc)
Кроссплатформенность:
Кроссплатформенность достигается за счет перевода байт-кода в машинный
язык при помощи JVM.
JVM сама по себе не является кроссплатформенной технологией.
Для запуска Java-программ в каждой архитектуре и операционной системе
должна быть специально разработанная JVM. Однако, поскольку
необходимость в JVM считается приоритетной, каждая современная
операционная система предоставляет её.

2.​ Java virtual machine (JVM), JIT-компилятор – определение, свойства,


функции. Принципы работы сборщика мусора.
JVM (Java Virtual Machine) — это виртуальная машина, которая выполняет
байт-код Java-программ. Она обеспечивает работу программ на разных
платформах, то есть позволяет запускать Java-приложения на различных
устройствах и операционных системах, где установлена эта программа.
Основное назначение JVM — предоставление среды выполнения для программ,
а точнее, непосредственно запуск и выполнение байт-кода. Но есть и другие
функции и особенности, которые придают JVM тот вид, который она сейчас
имеет.

Основные свойства и функции JVM:

●​ Платформенная независимость: JVM позволяет Java-программам


выполняться одинаково на всех платформах, реализуя принцип «WORA»
(Write Once, Run Anywhere).

●​ Управление памятью: JVM автоматически управляет памятью, выделяя


необходимое пространство для объектов и освобождая его посредством
сборки мусора. Это предотвращает утечки памяти и оптимизирует
использование ресурсов.

●​ Безопасность: JVM выполняет программы в изолированной среде и


проверяет байт-код на наличие некорректных или опасных частей,
обеспечивая безопасность выполнения.

●​ Многопоточность: JVM поддерживает многопоточность, позволяя


приложениям выполнять несколько потоков одновременно, что
способствует эффективному использованию ресурсов и повышению
производительности.

Благодаря этим свойствам и функциям, JVM значительно упрощает разработку,


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

JIT-компилятор (Just-In-Time компилятор) в Java — это компонент


виртуальной машины Java (JVM), который динамически преобразует байт-код в
машинный код непосредственно во время выполнения программы. Это
позволяет существенно повысить производительность Java-приложений по
сравнению с традиционной интерпретацией байт-кода.

Основные свойства и функции JIT-компилятора в Java:

●​ Динамическая компиляция: JIT-компилятор анализирует исполняемый


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

●​ Адаптивная оптимизация: JIT-компилятор собирает статистику о работе


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

●​ Многоуровневая компиляция: Современные JVM используют несколько


уровней компиляции (например, компиляторы C1 и C2), которые
применяют различные стратегии оптимизации в зависимости от частоты
использования методов. Это позволяет эффективно распределять ресурсы
компиляции и достигать оптимальной производительности.

●​ Управление памятью и безопасность: JIT-компилятор генерирует


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

Сборка мусора — это процесс автоматического управления памятью.


Освобождение памяти (путем очистки мусора) выполняется автоматически
специальным компонентом JVM — сборщиком мусора (Garbage Collector, GC).

Для сборки мусора используется алгоритм пометок (Mark & Sweep). Этот
алгоритм состоит из трех этапов:

●​ Mark (маркировка). На первом этапе GC сканирует все объекты и


помечает живые (объекты, которые все еще используются). На этом шаге
выполнение программы приостанавливается. Поэтому этот шаг также
называется "Stop the World" .

●​ Sweep (очистка). На этом шаге освобождается память, занятая объектами,


не отмеченными на предыдущем шаге.

●​ Compact (уплотнение). Объекты, пережившие очистку, перемещаются в


единый непрерывный блок памяти. Это уменьшает фрагментацию кучи и
позволяет проще и быстрее размещать новые объекты.
3.​ Системы сборки проектов. Фреймворк Apache Maven: определение,
структура, Maven Coordinates, POM-файл.
Apache Maven — это инструмент для автоматизации сборки проектов, который
в основном используется для проектов на языке Java. Он упрощает процесс
управления зависимостями, сборки, тестирования и развертывания
приложений. Maven позволяет разработчикам сосредоточиться на
написании кода, а не на управлении процессом сборки.

Определение

Maven предоставляет стандартизированный способ описания проекта, его


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

Структура проекта

●​ pom.xml: Основной файл конфигурации проекта.

●​ src/main/java: Исходный код приложения.

●​ src/main/resources: Ресурсы, используемые приложением (например, файлы


конфигурации).
●​ src/test/java: Исходный код тестов.

●​ src/test/resources: Ресурсы, используемые в тестах.

Maven Coordinates

Maven Coordinates — это уникальный идентификатор для артефактов (например,


библиотек или модулей), который включает в себя следующие элементы:

1.​ groupId: Уникальный идентификатор группы (обычно соответствует доменному


имени организации).

2.​ artifactId: Уникальный идентификатор артефакта (имя проекта).

3.​ version: Версия артефакта.

4.​ packaging: Тип пакета (например, jar, war, pom и т.д.).

POM-файл

POM (Project Object Model) — это XML-файл, который содержит информацию о


проекте и его конфигурации. Он является основным файлом для Maven и
определяет:

●​ Зависимости проекта.

●​ Плагины, используемые для сборки.

●​ Информацию о проекте (название, описание, версия и т.д.).

●​ Профили сборки, которые позволяют настраивать сборку для различных


сред.

4.​ Типы данных Java: простые и ссылочные. Простые (примитивные)


типы данных.
Примитивные типы — это данные, имеющие определённый формат и
значение. Они применяются для хранения простой информации, например
чисел, символов или логических значений. Ссылочные типы данных в Java
не содержат значения, а ссылаются на место, где они расположены. Проще
говоря, это не сами данные, а ссылки. Сюда входят строки, массивы, классы
и интерфейсы.

Обозначение вещественных типов отличается тем, что значение double


присваивается просто дробным числом, а к float в конце добавляется «f» —
например, float myFloat = 1.25f. Double используется,

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


пространстве. А float — в случаях, когда высокая точность не требуется,
например при обработке изображений, где точность в пикселях может
варьироваться от 0 до 1

char - работа с текстом

boolean - бул тип данных

Ссылочные типы данных

Строки. Состоят из символов Unicode, обозначаются классом String и


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

Массив. Это упорядоченная коллекция однотипных объектов с


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

Класс. Ссылочный тип данных, состоящий из переменных, то есть из


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

Интерфейс. Интерфейсы — только методы. Говоря простыми словами,


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

5.​ Переменные: статические и нестатические. Местные переменные,


область видимости переменных. Объявление и инициализация
переменных. Константы. Спецификаторы доступа.
В Java существует три типа переменных:

​ Локальные переменные. Объявляются в методах, блоках или конструкторах.


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

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


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

​ Статические переменные (переменные класса). Объявляются с использованием


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

Для объявления переменной в Java используют синтаксис: тип данных переменная


[= значение]. Если нужно объявить больше чем одну переменную указанного типа,
допускается применение списка с запятыми.

Для инициализации переменной используют оператор присваивания. Слева


указывается имя переменной, справа — её значение.

Константы позволяют задать переменные, которые больше не должны меняться. Как


правило, при записи имени константы применяют верхний регистр.

Спецификаторы доступа в Java включают:

●​ Public. Переменные доступны всем классам и объектам программы. Объявляется


при помощи ключевого слова public в начале строки.

●​ Protected. Области видимости переменных ограничены текущим пакетом и


подклассами. Объявляется ключевым словом protected.

●​ Package protected. Модификатор переменных, доступных только внутри пакета.


Объявления не требуется, отсутствие ключевых слов указывает на package
protected.

●​ Private. Переменные, доступные исключительно внутри класса. Определяется


ключевым словом private.
6.​ Комментарии: виды, особенности применения.
Практически все языки программирования позволяют оставлять в коде
комментарии. Они никак не используются кодом и нужны исключительно
для людей: чтобы программист оставлял пометки для себя и для других
программистов. Java комментарии игнорируются компилятором, т.к. они
несут смысл для разработчика, а не для пользователя. Поэтому можно
уменьшить размер компилируемых классов.

Комментарии в Java делятся на два типа:


●​ комментарий реализации (или комментарий кода);
●​ документирующий комментарий.

Комментарии кода используются для описания отдельных строк/блоков, а


комментарии для документирования используются, чтобы описать
спецификацию кода (его интерфейс), не зависящую от его реализации.

Комментарии в Java бывают трех видов:

Однострочные комментарии начинаются с //. После этих двух символов


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

➢​ Может занимать всю строку: // For Winterfell!


➢​ Может находиться на строке после какого-нибудь кода:
System.out.println("I am the King"); // => For Lannisters!

Многострочные комментарии начинаются с /* и заканчиваются на */.


Принято каждую строку начинать с символа *, хотя технически это и
необязательно:
/*
* The night is dark and
* full of terrors.
*/

*Документирующие комментарии начинаются с /** и заканчиваются на


*/. Уже для них обязательно каждую строку начинать с символа *.​
Документирующие комментарии — это подвид многострочных. При этом
несут дополнительную функцию — их можно собрать при помощи
специальной утилиты javadoc и выдать в качестве документации к вашему
коду.

7.​ Операции языка Java – арифметические, отношения и логические,


преобразования числовых типов.

Арифметические

Используются для выполнения базовых математических действий

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

Если оба операнда – целые числа, то результат также будет целым


(результат округляется вниз до ближайшего целого).

Если деление выполняется с участием типа double или float, результат


будет дробным.

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


Операторы инкремента-декремента
(https://pics.esputnik.com/repository/home/37116/images/msg/41711174/15597
38060892.gif )

Операции сравнения (отношения)


Сравнивают значения и возвращают результат типа boolean (true или false)

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

Работают с логическими значениями (true, false) и возвращают результат


типа boolean.

Операция отрицания унарная и применяется к одному операнду. Все


остальные операции — бинарные

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

&& ; AND Логическое И


(сокращенный)

|| ; OR Логическое ИЛИ
(сокращенный)

! ; NOT Логическое НЕ

^ ; XOR Исключающее ИЛИ


&& и || поддерживают "короткое замыкание" (если результат известен
после проверки первого операнда, второй не вычисляется).

НО есть аналогичные побитовые операторы (&, |), которые проверяют все


операнды.

Операции преобразования числовых типов

В Java числовые типы данных делятся на:

Целые: byte, short, int, long

С плавающей точкой: float, double

Неявное преобразование

Происходит, если тип с меньшим диапазоном значений преобразуется в


тип с большим:

int a = 10;

double b = a; // Автоматическое преобразование(сплошные линии на схеме)


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

int a = 2147483647;

float b = a; // от типа int к типу float

System.out.println(b); // 2.14748365E9

Явное преобразование

Происходит, если нужно преобразовать тип с большим диапазоном в тип с


меньшим:

long a = 4;

int b = (int) a;

При применении явных преобразований мы можем столкнуться с потерей


данных

double a = 10.5;

int b = (int) a; // Явное преобразование, дробная часть отбрасывается

8.​ Символьные строки, методы работы со строками Java.

Строки в Java представлены объектами класса String. Строка — это


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

Способы объявления (инициирования) строки:

-​ с помощью литералов:
-​ с помощью ключевого слова “new”:

-​ используя значения NULL:

Некоторые методы работы со строками в Java:

- Получение длины строки (метод length()).

- Получение символа в строке по его индексу (метод charAt()).

- Конкатенация строк (метод concat() и оператор + для объединения


двух строк).

- Сравнение строк (методы equals() и equalsIgnoreCase()).

- Извлечение подстроки (метод substring()).

- Преобразование строки в нижний или верхний регистр (методы


toLowerCase() и toUpperCase()).

- Удаление начальных и конечных пробелов (метод trim()).

- Разделение строки на массив подстрок (метод split()).

- Замена символов или подстрок (методы replace() и replaceAll()).

Для изменения строк в Java рекомендуется использовать классы


StringBuilder и StringBuffer, которые позволяют изменять строки без
создания новых объектов.

Строки в Java неизменяемы, то есть после создания строка не может быть


изменена. Например, методы concat(), toLowerCase() и replace()
возвращают новую строку, не изменяя исходную.
Иммутабельность строк в Java полезна для оптимизации памяти,
поскольку строки могут быть кешированы в строковом пуле, а также для
безопасности в многопоточном окружении. Но это надо учитывать при
использовании конкатенации строк, поскольку при этом создается много
временных объектов, что может снизить производительность.

9.​ Классы StringBuffer и StringBuilder.


Класс String представляет собой последовательность символов. Все
определенные в программе строковые литералы, вроде "This is String" —
это экземпляры класса String.

У String есть две фундаментальные особенности:

●​ это immutable (неизменяемый) класс

●​ это final класс

В общем, у класса String не может быть наследников (final) и экземпляры


класса нельзя изменить после создания (immutable).

После создания строк с ними часто совершается множество операций:

●​ перевод строк в разные регистры;

●​ извлечение подстрок;
●​ конкатенация;
●​ и т.д.

НО! В силу неизменности класса String, в результате каждой операции


создаются новые экземпляры строк, а старые отбрасываются, порождая
большое количество “мусора”.

Чтобы справиться с созданием временного мусора из-за модификаций


объекта String, можно использовать класс StringBuffer.

Это mutable класс, т.е. изменяемый. Объект класса StringBuffer может


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

●​ StringBuffer() — создаст пустой (не содержащий символов) объект

●​ StringBuffer(String str) — создаст объект на основе переменной str


(содержащий все символы str в той же последовательности)

StringBuffer sb = new StringBuffer();​


StringBuffer sb2 = new StringBuffer("Not empty");

Для работы со строками у класса StringBuffer есть ряд методов.


Перечислим основные:

●​ .append — конкатенация строк. Метод перегружен и может


принимать различные аргументы.

●​ .delete(int start, int end) — удаляет подстроку символов начиная с


позиции start, заканчивая end
●​ .deleteCharAt(int index) — удаляет символ в позиции index
●​ .insert(int offset, String str) — вставляет строку str в позицию offset.
Метод insert также перегружен и может принимать различные
аргументы
●​ .replace(int start, int end, String str) — заменит все символы начиная с
позиции start до позиции end на str
●​ .reverse() — меняет порядок всех символов на противоположный
●​ .substring(int start) — вернет подстроку, начиная с позиции start
●​ .substring(int start, int end) — вернет подстроку, начиная с позиции
start до позиции end

Преимущества:

1.​ StringBuffer — изменяемый класс, поэтому при работе с ним не


возникает такого же количества мусора в памяти, как со String.
Поэтому если над строками проводится много модификаций, лучше
использовать StringBuffer.
2.​ StringBuffer — потокобезопасный класс. Его методы
синхронизированы, а экземпляры могут быть использованы
несколькими потоками одновременно.

Недостатки: С одной стороны, потокобезопасность — преимущество


класса, а другой — недостаток. Синхронизированные методы работают
медленнее не сихнронизированных.

StringBuilder — класс, представляющий последовательность символов.


Он очень похож на StringBuffer во всем, кроме потокобезопасности.

StringBuilder предоставляет API, аналогичный API StringBuffer’a.

Разница лишь в том, что StringBuffer потокобезопасен, и все его методы


синхронизированы, а StringBuilder — нет. Это единственная особенность.

StringBuilder в Java работает быстрее StringBuffer’а благодаря


несинхронизированности методов.

Поэтому в большинстве случаев, кроме многопоточной среды, лучше


использовать StringBuilder.

10.​Массивы Java: объявление, инициализация. Основные методы класса


Arrays. Доступ к элементам массивов, итерация массивов.
Двумерные массивы.
Массивы в Java — это структура данных, которая позволяет хранить набор
элементов одного типа.

Для объявления массива необходимо:

1.​ Указать тип элементов.

2.​ Использовать квадратные скобки [].

Пример: int[] numbers; // Массив целых чисел

Инициализация массива

●​ Явная: При создании сразу задаются значения.

●​ Неявная: Используется конструктор new, значения по умолчанию (0, null,


false).
Доступ к элементам массива

Доступ осуществляется по индексу (начинается с 0). Изменить или получить


элемент массива можно так:

Итерация по массиву

Для работы с каждым элементом массива можно использовать:

●​ Цикл for

●​ Усовершенствованный for (foreach)

●​ Стримы (с использованием Java Streams, для Java 8+)

Двумерные массивы
●​ Объявление и инициализация:

●​ Доступ к элементам двумерного массива:

●​ Итерация:

Основные методы класса Arrays

●​ Сортировка массива sort()

●​ Вывод массива в строку toString()

●​ Поиск элемента binarySearch() - Работает только на отсортированном


массиве

●​ Копирование массива copyOf()

●​ Сравнение массивов equals()

●​ Заполнение массива fill() - Заполняет массив одинаковыми значениями.

11.​Управляющие конструкции Java: ветвление, циклы. Цикл foreach.


Управляющие конструкции в Java используются для управления потоком
выполнения программы. Основные типы:
1.​ Ветвления - условные операторы, выполнение определенной
команды или набора команд только при условии истинности
некоторого логического выражения;

2.​ Циклы - повторение набора инструкций.

Ветвления

Основное предназначение оператора ветвления – это реализация


разветвляющихся алгоритмов.

1.​ if, if-else

2.​ else if

3.​ switch

Синтаксис оператора ветвления if else

Синтаксис оператора ветвления else if

В программировании часто встречается необходимость создания


каскадных операторов ветвления. Синтаксис такой структуры имеет вид :

Синтаксис оператора ветвления switch

Конструкция if else может оказаться неудобной, если вы стоите перед


необходимостью сделать выбор из нескольких вариантов. Оператор switch
применяется для проверки одного выражения на несколько значений.
Выполнение кода начинается с метки case, соответствующей значению
выражения choice, и продолжается до следующего оператора break или
конца оператора switch. Если ни одна метка не совпадает со значением
переменной, выполняется раздел default, если он предусмотрен.

Метка case должна быть целочисленной. Нельзя проверять строки. Все


значения case должны быть уникальными литералами. Если в двух
операторах case будут одинаковые значения, то транслятор выдаст
сообщение об ошибке.

Циклы

В java существует два типа циклов:

1.​ цикл типа «пока» - while и do…while - предназначен для повторения


какого-то действия до тех пор, пока выполняется некоторое условие.
Пример: увеличивать значение переменной на 3 до тех пор, пока оно
не станет трехзначным.

2.​ цикл типа «n-раз» - for (инициализация; условие; итерация) -


предназначен для повторения каких-то действий заранее известное
количество раз. ​
Пример: найти факториал числа 6.

Циклы while и do…while

Оператор while повторяет указанные действия до тех пор, пока его


выражение имеет истинное значение.

Синтаксис цикла while


Условие необходимости повторения цикла проверяется перед каждым
шагом цикла, в том числе перед самым первым.

Java предлагает также возможность использования цикла с постпроверкой


условия. Для его записи используется конструкция из операторов
do…while.

Тело цикла do…while выполняется по крайней мере один раз. Этот


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

Цикл for

Оператор for содержит три параметра : параметр инициализации, параметр


повторения, параметр итерации.

Синтаксис цикла for

В первом параметре определяют переменную, с помощью которой будет


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

Используется для итерации по коллекциям или массивам. Позволяет


упростить работу с данными, исключив необходимость управления
индексами.
12.​Перечислить и дать описание основных принципов
объектно-ориентированного программирования (ООП). Достоинства
и недостатки ООП.
Принципы:
●​ Инкапсуляция
Инкапсуляция означает скрытие деталей реализации объекта и
предоставление только интерфейса для взаимодействия с ним. Это
позволяет изолировать изменения в одной части программы от других
частей, что делает код более надежным и устойчивым к изменениям.
●​ Наследование
Наследование позволяет создавать новые классы на основе
существующих. Это способствует повторному использованию кода и
созданию иерархий классов. Наследование позволяет наследникам
использовать свойства и методы предков и переопределять или
расширять их, если это необходимо.
●​ Полиформизм
Полиморфизм означает способность объектов разных классов обладать
общим интерфейсом. Это позволяет обрабатывать объекты разных
типов с помощью общих методов и функций. Полиморфизм делает код
более гибким и расширяемым.
●​ Абстракция
Абстракция - это процесс выделения общих характеристик объектов и
создание абстрактных классов или интерфейсов для их представления.
Абстракция помогает упростить модель системы, делая её более
понятной и управляемой.

Достоинства:
●​ Модульность
Инкапсуляция объектов в себе упрощает разработку, уменьшает
количество ошибок и ускоряет разработку при участии большого
количества программистов, так как каждый может работать независимо
друг от друга.
●​ Расширяемость
ООП-код легче развивать, дополнять и менять. Этому способствует
независимая модульная структура.
●​ Повторное использование кода
Благодаря абстракциям, полиморфизму и наследованиям можно не
писать один и тот же код много раз, что заметно ускоряет создание
нового ПО.
●​ Гибкость
Полиморфизм позволяет быстро адаптировать ООП-код под свои нужды,
не описывая новые функции и объекты.
●​ Безопасность
Извне получить доступ к инкапсулированному коду нельзя, поэтому
сломать код – задача не из простых.
●​ Простота восприятия
Использование ООП упрощает понимание кода за счет взаимодействия с
объектами, а не логикой. Не нужно углубляться в то, как построено ПО,
чтобы модифицировать его.

Недостатки:
●​ Больший объем кода
ООП приводит появлению большего количества кода, нежели в
императивном программировании.
●​ Медленные программы
Объекты потребляют больше оперативной памяти, чем примитивные
типы данных
●​ Специфичность
Ряд задач могут лучше решаться в императивном, логическом или
функциональном стиле, где использование ООП не даст выигрыша.

13.​Определение класса. Объявление класса. Спецификаторы доступа.


Отношения между классами Java (наследование, зависимость,
агрегирование). Статические члены класса. Переменные класса.
Класс в Java — это шаблонная конструкция, которая позволяет описать в
программе объект, его свойства (атрибуты или поля класса) и поведение (методы
класса).

Объявление класса начинается с ключевого слова class, после которого


указывается идентификатор — имя класса. Затем в фигурных скобках
перечисляются атрибуты и методы класса.

class Dog {

int age; // возраст

String name; // кличка

public void voice() {

for (int i = 1; i <= age; i++) {

System.out.println("гав-гав");

}
}

Спецификаторы доступа в Java (public, private, protected, default)


ограничивают видимость и доступ к классам, переменным, методам и
конструкторам

1. Public

Модификатор public означает, что элемент (класс, метод, переменная или


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

public class MyClass {

public int myVariable;

public void myMethod() {

// ...

2. Private

Модификатор private делает элемент доступным только внутри класса, в котором


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

class MyClass {

private int myVariable;

private void myMethod() {


// ...

3. Protected

Модификатор protected делает элемент доступным только для классов из того же


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

class MyClass {

protected int myVariable;

protected void myMethod() {

// ...

4. Default (пакетный доступ)

Если модификатор доступа не указан явно, то используется уровень доступа по


умолчанию, который также называется «пакетный доступ». Элементы с таким
уровнем доступа доступны только для классов из того же пакета, что и
определенный элемент.

class MyClass {

int myVariable; // default access

void myMethod() { // default access

// ...

}
}

Наследование — механизм, который позволяет описать новый класс на основе


существующего (родительского). При этом свойства и функциональность
родительского класса заимствуются новым классом. В Java для реализации
наследования используется ключевое слово extends.

Агрегация — отношение, когда один объект выступает в качестве части


другого. Пример: класс Library имеет поле, содержащее объекты класса Book.
Книги могут быть добавлены или удалены из библиотеки, но они также могут
существовать независимо от библиотеки.

Композиция — отношение, когда один объект является частью другого объекта


и не может существовать независимо от него. Пример: класс Car содержит
объект класса Engine в качестве своего поля. Когда объект Car удаляется, объект
Engine также удаляется.

Статические члены класса в Java — это поля и методы, которые принадлежат


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

Статические переменные (статические поля) принадлежат классу, а не


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

Для объявления статических переменных, констант, методов и инициализаторов


перед их объявлением указывается ключевое слово static.

14.​Объект класса. Создание объекта. Конструктор класса, конструктор


по умолчанию. Ключевое слово this. Перегрузка конструкторов.
Доступ к переменным экземпляра.

Объект класса

Объект класса — это конкретный экземпляр, созданный на основе определения


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

Создание объекта

Для создания объекта класса в Java используется оператор new, который


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

1MyClass myObject = new MyClass();

Конструктор класса

Конструктор — это специальный метод, который вызывается при создании


объекта. Он имеет то же имя, что и класс, и не имеет возвращаемого типа.
Конструктор может принимать параметры, которые позволяют
инициализировать переменные экземпляра.
Пример конструктора:

1public class MyClass {

2 private int value;

4 // Конструктор с параметром

5 public MyClass(int value) {

6 this.value = value; // Инициализация переменной экземпляра

7 }

8}

Конструктор по умолчанию

Конструктор по умолчанию — это конструктор без параметров, который


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

Пример конструктора по умолчанию:

1public class MyClass {

2 private int value;

4 // Конструктор по умолчанию

5 public MyClass() {

6 this.value = 0; // Инициализация переменной экземпляра

7 }

8}

Ключевое слово this


Ключевое слово this используется для ссылки на текущий объект класса. Оно
помогает различать переменные экземпляра и параметры метода или
конструктора, если они имеют одинаковые имена.

Пример использования this:

1public class MyClass {

2 private int value;

4 public MyClass(int value) {

5 this.value = value; // 'this.value' ссылается на переменную


экземпляра, а 'value' - на параметр

6 }

7}

Перегрузка конструкторов

Перегрузка конструкторов — это возможность создавать несколько


конструкторов с разными параметрами в одном классе. Это позволяет
создавать объекты с различными начальными значениями.

Пример перегрузки конструкторов:

1public class MyClass {

2 private int value;

4 // Конструктор по умолчанию

5 public MyClass() {

6 this.value = 0;

7 }

9 // Конструктор с параметром

10 public MyClass(int value) {


11 this.value = value;

12 }

13

14 // Конструктор с двумя параметрами

15 public MyClass(int value1, int value2) {

16 this.value = value1 + value2;

17 }

18}

Доступ к переменным экземпляра

Переменные экземпляра (поля) класса могут быть доступны через методы


класса, включая конструкторы. Для доступа к переменным экземпляра можно
использовать this или просто имя переменной, если нет конфликта имен.

Пример доступа к переменным экземпляра:

1public class MyClass {

2 private int value;

4 public MyClass(int value) {

5 this.value = value; // Инициализация переменной экземпляра

6 }

8 public int getValue() {

9 return this.value; // Доступ к переменной экземпляра

10 }

11}
15.​Методы, объявление, имя. Статические методы. Доступ к методам.
Спецификаторы доступа.
1. Объявление метода
Метод в Java объявляется следующим образом:

[модификатор доступа] [другие модификаторы] тип_возвращаемого_значения


имяМетода (параметры) {}

Пример:

public int сложить(int a, int b) {return a + b;}

2. Имя метода
-​ Должно следовать правилам именования идентификаторов в Java.

-​ Должно быть глаголом, если метод выполняет действие.

3. Статические методы
-​ Объявляются с модификатором static.
-​ Принадлежат классу, а не объекту.
-​ Вызываются без создания экземпляра класса.

Пример:

public class MathUtils {

public static int multiply(int a, int b) {return a * b; }}

Вызов статического метода:

int result = MathUtils.multiply(5, 10);

4. Доступ к методам (Вызов)


Методы можно вызывать из других методов класса или из других классов:

Экземплярные методы (не статические): вызываются через объект.

MyClass obj = new MyClass();

obj.instanceMethod()

Статические методы: вызываются через имя класса.

MyClass.staticMethod();

5. Спецификаторы доступа
Определяют, где можно использовать метод.

Специфика Доступ внутри Доступ в Доступ в Доступ


тор класса пакете наследниках извне

public да да да да

protected да да да нет

default да да нет нет

private да нет нет нет

Пример:

public class Example {

private void privateMethod() {} // Доступ только внутри класса

protected void protectedMethod() {} // Доступ в классе и наследниках

public void publicMethod() {} // Доступ везде

6. Важные ключевые слова


-​ this – ссылается на текущий объект.

-​ super – вызывает метод родительского класса.


-​ final – запрещает переопределение метода.
-​ abstract – объявляет метод без реализации (для абстрактных классов).

Пример использования final:

class Base {

public final void display() {

System.out.println("Cannot override this method.");

}
16.​Пакеты Java. Импорт пакетов и классов. Статический импорт.
Пакетом (пространством имен) в Java называется структура вложенных по
какому-то признаку папок с размещенными в них классами (интерфейсами,
перечислениями, аннотациями), необходимыми проекту.

Вы можете думать о пакетах как о папках на вашем компьютере, в которых


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

Конструкция import позволяет "импортировать" один или несколько


классов и интерфейсов и после этого обращаться к ним не по полному
имени (включающему название package-а), а по непосредственному
имени.

Импорт пакетов и классов в Java осуществляется с помощью директивы


import, которая указывается после директивы package. Директива указывается
в самом начале кода, после чего идёт имя подключаемого класса. Исключение
составляют классы из пакета java.lang (например, String), которые
подключаются в программу автоматически

Статический импорт в Java — особая форма импорта, для которой вместе с


директивой import используется модификатор static. Благодаря статическому
импорту можно использовать статические методы без названия класса.
Например, писать не Math.sqrt(20), а sqrt(20), так как функция sqrt(), которая
возвращает квадратный корень числа, является статической

17.​Вложенные и внутренние классы Java. Статические и нестатические


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

●​ Применяются в тех случаях, когда нужно написать небольшой


вспомогательный код для другого класса
●​ Создаются, чтобы скрыть переменные и методы от внешнего мира
(еще один способ ограничения области видимости)
●​ Есть смысл использовать, если предполагается, что они будут
использовать элементы родителя, чтобы не передавать лишнего в
конструкторах

class OuterClass {
...
class NestedClass {
...
}
}

Они делятся на 2 вида:


1.​ Non-static nested classes — нестатические вложенные классы.
По-другому их еще называют inner classes — внутренние классы.
Является членом внешнего класса и имеет доступ ко всем его
членам, включая приватные. Однако для создания объекта такого
класса требуется объект внешнего класса.
2.​ Static nested classes — статические вложенные классы.
Объявляется с модификатором static. Он является членом внешнего
класса, но не имеет доступа к нестатическим членам внешнего
класса напрямую.

Вложенные классы используются, когда один класс логически связан с


другим, а внутренние — для тесной интеграции с внешним классом.

Внутренние классы — это классы для выделения в программе некой


сущности, которая неразрывно связана с другой сущностью. Помимо того,
что внутренний класс может быть просто внутренним классом, он еще
бывает:
●​ локальным классом (local class) - класс, объявленный внутри метода
●​ анонимным классом (anonymous class) - определяется и
используется на месте.

18.​Наследование. Подклассы и суперклассы. Доступ к членам класса.


Конструкторы при наследовании, ключевое слово super.

Наследование – это механизм объектно-ориентированного


программирования, который позволяет создавать новые классы
(подклассы), наследуя свойства и поведение (методы) существующего
класса (суперкласса).

С помощью наследования можно расширить функционал уже имеющихся


классов за счет добавления нового функционала или изменения старого.

Чтобы объявить один класс наследником от другого, надо использовать


после имени класса-наследника ключевое слово extends, после которого
идет имя базового класса.

Для класса Employee базовым является Person, и поэтому класс Employee


наследует все те же поля и методы, которые есть в классе Person.
Доступ к членам класса

1.​ public: доступен в любом месте программы.

2.​ protected: доступен в том же пакете и в подклассах.

3.​ private: доступен только внутри того же класса.

4.​ Модификатор доступа по умолчанию: доступен только в пределах


одного пакета.

Если в базовом классе определены конструкторы, то в конструкторе


производного классы необходимо вызвать один из конструкторов базового
класса с помощью ключевого слова super. Например, класс Person имеет
конструктор, который принимает один параметр. Поэтому в классе
Employee в конструкторе нужно вызвать конструктор класса Person. То
есть вызов super(name) будет представлять вызов конструктора класса
Person.

При вызове конструктора после слова super в скобках идет перечисление


передаваемых аргументов. При этом вызов конструктора базового класса
должен идти в самом начале в конструкторе производного класса. Таким
образом, логика делегируется конструктору базового класса.
class Employee extends Person{

public Employee(String name){

super(name);​ // если базовый класс определяет конструктор


// то производный класс должен его вызвать

(то-есть если определять конструктор, то в начале обязательно вызвать


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

Другое использование слова super:

для вызова метода суперкласса

19.​Иерархия наследования Java. Преобразование типов при


наследовании. Ключевое слово instanceof.
Иерархия наследования в Java — это набор классов, связанных
отношением наследования. В терминологии Java наследуемый класс
называется суперклассом, а наследующий класс — подклассом. Подкласс
наследует все члены, определённые в суперклассе, добавляя к ним
собственные, особые элементы.

Класс java.lang.Object всегда находится на вершине любой иерархии


наследования Java. Все классы, за исключением самого класса Object,
наследуют (или прямо, или косвенно) от этого класса.

щас будет пример, на нем легче понять эту дичь

Допустим, у нас есть следующие классы:


// класс человека

class Person {

private String name;

// служащий некоторой компании

class Employee extends Person{

private String company;

*extends - значит наследует класс Person

// класс клиента банка

class Client extends Person{


private int sum; // Переменная для хранения суммы на счете

private String bank;

В этой иерархии классов следующее наследие:

Суперклассы обычно размещаются выше подклассов, поэтому на вершине


наследования находится класс Object, а в самом низу Employee и Client.

Восходящее преобразование (upcasting) в Java происходит, когда объект


класса-наследника преобразуется в объект класса-родителя. Такое
преобразование осуществляется автоматически. (Объект подкласса также
представляет объект суперкласса. Объект подкласса наследует все от
родителя - объект Employee всегда является также объектом Person)

Пример восходящего преобразования (от потомка к предку):


Обратное не всегда верно. Например, объект Person не всегда является
объектом Employee или Client. Нисходящее преобразование (downcasting)
происходит, когда объект класса преобразуется в объект
класса-наследника. Во время нисходящего преобразования необходимо
явное приведение типа, так как объект класса-наследника содержит
дополнительные методы и поля, которых нет в родительском классе.

Пример нисходящего преобразования (от предка к потомку):

(display означает отображение объекта)

В данном случае переменная типа Object хранит ссылку на объект Client.


Мы можем без ошибок привести этот объект к типам Person или Client. Но
при попытке преобразования к типу Employee мы получим ошибку во
время выполнения. Так как kate не представляет объект типа Employee.

instanceof
Ключевое слово instanceof проверяет, является ли объект экземпляром
конкретного класса или интерфейса. Оно сравнивает экземпляр с типом и
возвращает значение true или false.

Оператор instanceof проверяет именно происхождение объекта, а не


переменной.
20.​Полиморфизм в Java. Перегрузка и переопределение методов.
Полиморфизм является одним из основных принципов ООП. Это
способность объекта использовать методы производного класса, который
не существует на момент создания базового класса. Полиморфизм
позволяет использовать объекты производного класса как объекты
базового класса, выполняя при этом методы производного класса.

Например, есть базовый класс Animal и производные от него классы Dog и


Cat. У всех этих классов есть метод makeSound(). Если создать массив
объектов класса Animal и поместить в него объекты классов Dog и Cat, то
при вызове метода makeSound() для каждого из объектов в массиве, будет
вызван соответствующий метод класса, которому принадлежит объект.

class Animal {​
​ void makeSound() {System.out.println("Some generic animal sound");}​
}

class Dog extends Animal {​


​ @Override​
​ void makeSound() {System.out.println("Woof");}​
}

class Cat extends Animal {​


​ @Override​
​ void makeSound() {System.out.println("Meow");}​
}

public class PolymorphismExample {​


​ public static void main(String[] args) {​
​ ​ Animal[] animals = { new Dog(), new Cat() };​
​ ​ for (Animal animal : animals) {​
​ ​ ​ animal.makeSound(); // Вызов метода конкретного класса​
​ ​ }​
​ }​
}

Переопределение в Java — это возможность класса наследника


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

Например, класс Shape имеет метод getArea(), который возвращает


площадь фигуры. Классы Circle и Rectangle, наследующие класс Shape,
переопределяют метод getArea() для предоставления своей собственной
реализации расчета площади.​
Чтобы переопределить метод, нужно: ​
​ 1) В классе-наследнике создать метод с таким же именем, как в родительском
классе.​
​ 2) Добавить перед ним аннотацию @Override. Эта аннотация сообщит
компилятору, что это не ошибка, а намеренное переопределение метода. ​
​ 3) Написать собственную реализацию для каждого класса-наследника. Если
этого не сделать, то будет использована реализация родительского класса.

Перегрузка методов в Java — это возможность класса иметь два или более
метода с одинаковыми именами, но разными параметрами. Методы могут
отличаться количеством параметров, типом параметров или их порядком.

Например, в классе Rectangle может быть два метода setDimensions(): один


принимает два параметра (длину и ширину прямоугольника), а второй —
один параметр (длину стороны, если прямоугольник является квадратом).

class Rectangle { ​
​ double length, width; ​
​ void setDimensions(double length, double width) { //прямоугольник​
​ ​ this.length = length; ​
​ ​ this.width = width; ​
​ }​
​ void setDimensions(double side) { //квадрат​
​ ​ this.length = side;​
​ ​ this.width = side; ​
​ }​
​ double getArea() { return length * width; } ​
}
21.​Абстрактные методы и классы Java.
Абстрактный класс — это класс, который не может быть создан (нельзя создать
его экземпляр). Он предназначен для наследования и содержит как
реализованные, так и абстрактные (незавершённые) методы.​

Особенности абстрактных классов:
●​ При объявлении используется ключевое слово abstract: abstract
class class_name{}

●​ Может содержать абстрактные методы (без тела) и обычные


методы (с реализацией).
●​ Может содержать поля, конструкторы и статические методы.
Если класс наследует абстрактный класс, он обязан реализовать все его
абстрактные методы, если сам не является абстрактным.​

Синтаксис:​ ​ ​ ​ Пример наследования: ​ ​

Абстрактный метод — это метод, объявленный без тела (без реализации) в


абстрактном классе. Он служит как "шаблон", который обязан быть реализован в
подклассах.​

Синтаксис: abstract class class_name{ abstract void method_name(); }​

Особенности абстрактных методов: Абстрактные методы не могут быть final,
static или private, так как их реализация всегда определяется в подклассах.​

Отличия абстрактного класса от интерфейса

1.​ Наследование:

○​ Абстрактный класс может наследоваться только одним классом


(single inheritance).
○​ Интерфейс может быть реализован несколькими классами.
2.​ Полиморфизм:
○​ Абстрактный класс поддерживает частичную реализацию методов.
○​ В интерфейсах до Java 8 методы не могли иметь реализации, однако
начиная с Java 8 появилась поддержка default-методов.
3.​ Модификаторы:
○​ В абстрактных классах методы могут быть protected или public.
○​ Методы интерфейсов по умолчанию являются public.

Когда использовать абстрактные классы

●​ Если требуется предоставить базовую реализацию для нескольких


связанных классов.

●​ Если нужно определять общие поля или методы с реализацией.


●​ Если есть смысловая связь "is-a" между базовым и производным
классами. (связь заключается в том, что производные классы
рассматриваются как специализированные версии базового класса)

22.​Интерфейсы Java: определение интерфейса, реализация интерфейса.


Преимущества применения интерфейсов. Переменные интерфейсов.
Наследование интерфейсов. Методы по умолчанию. Статические
методы интерфейсов.
Интерфейс описывает поведение, которым должны обладать классы,
реализующие этот интерфейс. «Поведение» — это совокупность методов.

Создание интерфейса очень похоже на создание обычного класса, только


вместо слова class мы указываем слово interface.

Мы создали интерфейс Swimmable — «умеющий плавать». Это что-то


вроде нашего пульта, у которого есть одна «кнопка»: метод swim() —
«плыть».

Чтобы использовать интерфейс, его методы должны реализовать какие-то


классы нашей программы.

Давай придумаем класс, объекты которого подойдут под описание


«умеющий плавать». Например, подойдет класс утки — Duck:
Класс Duck «связывается» с интерфейсом Swimmable при помощи
ключевого слова implements. Это значит, что класс, связанный с каким-то
интерфейсом, должен реализовать все его методы. В нашем классе Duck
прямо как в интерфейсе Swimmable есть метод swim(), и внутри него
содержится какая-то логика.

Если бы мы не создали бы метод swim() в классе Duck, компилятор выдал


бы нам ошибку.

Преимущества применения интерфейсов

1.​ Множественное наследование: Java не поддерживает множественное


наследование классов, но с помощью интерфейсов можно
реализовать поведение из нескольких источников.

2.​ Полиморфизм: Код становится более гибким, так как объекты могут
быть представлены через интерфейсы.

3.​ Поддержка принципа "Программируй на уровне интерфейсов": Это


упрощает замену реализации без изменения кода, который
взаимодействует с интерфейсом.

Переменные в интерфейсе по умолчанию являются:

1.​ public static final (константы).


2.​ Неизменяемыми.
Интерфейсы могут наследовать другие интерфейсы с помощью ключевого
слова extends. При этом дочерний интерфейс наследует все методы
родительского интерфейса.

Класс, реализующий дочерний интерфейс, должен реализовать методы как


дочернего, так и родительского интерфейса

Интерфейсы кроме определения методов могут иметь их реализацию по


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

23.​Исключения (exception) Java. Синтаксис объявления исключений.


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

Иерархия и классификация

В основе всего лежит класс Throwable. Все возможные конфликты кода с


машиной и пользователем описаны в этом классе.
Для удобства обработки и чтения класс Throwable имеет подклассы Error и
Exception.
Error – критические ошибки, которые не следует пытаться обрабатывать в
собственной программе, поскольку они связаны с проблемами уровня
JVM(виртуальной машины). Например, исключения такого рода возникают, если
закончилась память, доступная виртуальной машине.
Exception – является результатом проблем в программе, которые, в принципе,
решаемые и предсказуемые. Например, произошло деление на ноль в целых
числах.

Все исключения делятся на 2 типа:


●​ Checked (проверяемые *желтые*)
Наличие\обработка Checked исключений проверяется на этапе
компиляции. Они должны обрабатываться блоком catch или описываться
в сигнатуре метода.
Примеры: ArithmeticException: исключение, возникающее при делении на
ноль, IndexOutOfBoundException: индекс вне границ массива

●​ Unchecked (непроверяемые *красные*)


Наличие\обработка Unchecked исключений происходит на этапе
выполнения. Исключения могут не обрабатываться и не быть
описанными.
Примеры: InterruptedException: поток прерван другим потоком,
ClassNotFoundException: невозможно найти класс.

Синтаксис:
Для обработки исключений java используются следующие операторы: try,
catch, finally, throw, throws. Первые три — стандартная структура блока
обработки.

В блоке finally набор обязательных действий при возникновении ошибки(запись


данных и пр.). Блок исполняется всегда, вне зависимости от срабатывания
catch.
throw – используется для явного возбуждения исключения.
throws – используется в сигнатуре методов для предупреждения, о том что
метод может выбросить исключение.
Правила для исключений при наследовании:
●​ Переопределяемый метод в подклассе не может выбрасывать
контролируемые исключения, которые выше по иерархии чем
исключения в методе супер класса(например, в супер классе
IOException, а в подклассе пытаемся кинуть Throwable).
●​ Конструктор подкласса должен включить в свой блок throws все классы
исключений или их супер классы из блока throws конструктора супер
класса, к которому он обращается при создании объекта.

24.​Коллекции: Java collections framework. Классификация интерфейсов


коллекций. Интерфейс Collection.
Java Collection Framework — иерархия интерфейсов и их реализаций, которая
является частью JDK и позволяет разработчику пользоваться большим
количеством структур данных.

Для хранения наборов данных в Java предназначены массивы. Однако их не


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

Классы коллекций располагаются в пакете java.util, поэтому перед применением


коллекций следует подключить данный пакет.

Хотя в Java существует множество коллекций, но все они образуют стройную и


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

●​ Collection базовый интерфейс для всех коллекций и других


интерфейсов коллекций

●​ Queue: наследует интерфейс Collection и представляет функционал для


структур данных в виде очереди

●​ Deque: наследует интерфейс Queue и представляет функционал для


двунаправленных очередей

●​ List: наследует интерфейс Collection и представляет функциональность


простых списков

●​ Set: также расширяет интерфейс Collection и используется для


хранения множеств уникальных объектов
●​ SortedSet: расширяет интерфейс Set для создания сортированных
коллекций

●​ NavigableSet: расширяет интерфейс SortedSet для создания коллекций,


в которых можно осуществлять поиск по соответствию

●​ Map: предназначен для созданий структур данных в виде словаря, где


каждый элемент имеет определенный ключ и значение. В отличие от
других интерфейсов коллекций не наследуется от интерфейса
Collection

Эти интерфейсы частично реализуются абстрактными классами:


AbstractCollection, AbstractList, AbstractSet, AbstractQueue, AbstractSequentialList,
AbstractMap.

С помощью применения вышеописанных интерфейсов и абстрактных классов в


Java реализуется широкая палитра классов коллекций - списки, множества,
очереди, отображения и другие, среди которых можно выделить следующие:
ArrayList, LinkedList, ArrayDeque, HashSet, TreeSet, LinkedHashSet, PriorityQueue,
TreeMap

Схематично всю систему можно представить следующим образом:

Интерфейс Collection является базовым для всех коллекций, определяя основной


функционал:
Интерфейс Collection является обобщенным и расширяет интерфейс Iterable,
поэтому все объекты коллекций можно перебирать в цикле по типу for-each.

Среди методов интерфейса Collection можно выделить следующие:

●​ boolean add(E item): добавляет в коллекцию объект item. При удачном


добавлении возвращает true, при неудачном - false

●​ boolean addAll(Collection<? extends E> col): добавляет в коллекцию все


элементы из коллекции col. При удачном добавлении возвращает true,
при неудачном - false

●​ void clear(): удаляет все элементы из коллекции

●​ boolean contains(Object item): возвращает true, если объект item


содержится в коллекции, иначе возвращает false

●​ boolean isEmpty(): возвращает true, если коллекция пуста, иначе


возвращает false

●​ Iterator<E> iterator(): возвращает объект Iterator для обхода элементов


коллекции

●​ boolean remove(Object item): возвращает true, если объект item удачно


удален из коллекции, иначе возвращается false

●​ boolean removeAll(Collection<?> col): удаляет все объекты коллекции


col из текущей коллекции. Если текущая коллекция изменилась,
возвращает true, иначе возвращается false

●​ boolean retainAll(Collection<?> col): удаляет все объекты из текущей


коллекции, кроме тех, которые содержатся в коллекции col. Если
текущая коллекция после удаления изменилась, возвращает true, иначе
возвращается false

●​ int size(): возвращает число элементов в коллекции

●​ Object[] toArray(): возвращает массив, содержащий все элементы


коллекции
Все эти и остальные методы, которые имеются в интерфейсе Collection,
реализуются всеми коллекциями, поэтому в целом общие принципы работы с
коллекциями будут одни и те же. Единообразный интерфейс упрощает
понимание и работу с различными типами коллекций. Так, добавление элемента
будет производиться с помощью метода add(), который принимает добавляемый
элемент в качестве параметра. Для удаления вызывается метод remove(). Метод
clear() будет очищать коллекцию, а метод size() возвращать количество
элементов в коллекции.

25.​Списки. Интерфейс List. Основные классы, реализующие интерфейс


List. ArrayList, особенности, методы. Comparator.
Интерфейс List

Интерфейс List определяет основные операции для работы с упорядоченными


коллекциями, такие как добавление, удаление, получение и изменение
элементов. Основные методы интерфейса List включают:

●​ add(E e): добавляет элемент в конец списка.

●​ add(int index, E element): вставляет элемент в указанную позицию.

●​ get(int index): возвращает элемент по указанному индексу.

●​ remove(int index): удаляет элемент по указанному индексу.

●​ set(int index, E element): заменяет элемент по указанному индексу.

●​ size(): возвращает количество элементов в списке.

●​ isEmpty(): проверяет, пуст ли список.

●​ contains(Object o): проверяет, содержится ли элемент в списке.

Основные классы, реализующие интерфейс List

Существует несколько классов, которые реализуют интерфейс List. Наиболее


распространенные из них:

1.​ ArrayList: динамический массив, который может изменять свой размер.


Он обеспечивает быстрый доступ к элементам по индексу, но операции
вставки и удаления могут быть медленными, если они происходят не в
конце списка.

2.​ LinkedList: реализует двусвязный список. Он обеспечивает быструю


вставку и удаление элементов, но доступ по индексу медленнее, чем в
ArrayList.

3.​ Vector: устаревший класс, который также реализует динамический


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

ArrayList

ArrayList — это наиболее часто используемая реализация интерфейса List.

Он позволяет хранить элементы в виде массива, который может динамически


изменять свой размер. Основные особенности ArrayList:

●​ Динамическое изменение размера: при добавлении элементов, если


массив заполняется, ArrayList автоматически увеличивает его размер.

●​ Быстрый доступ: доступ к элементам по индексу осуществляется за


константное время (O(1)).

●​ Не синхронизирован: ArrayList не является потокобезопасным, поэтому


для многопоточных приложений следует использовать
Collections.synchronizedList() или CopyOnWriteArrayList.

Пример использования ArrayList:


Comparator

Comparator — это функциональный интерфейс, который используется для

определения порядка сортировки объектов. Он позволяет сравнивать два


объекта и определять, какой из них "меньше", "больше" или "равен". Comparator
может быть использован для сортировки коллекций, таких как List.

Пример использования Comparator для сортировки списка:

26.​Интерфейс Set. Основные реализации. HashSet. TreeSet.


важное про Set:
-​ Не допускает дубликатов.
-​ Не гарантирует порядок хранения элементов (зависит от конкретной
реализации).
-​ Позволяет выполнять операции, такие как добавление, удаление и
проверку на наличие элемента.
пример HashSet

-​ Основан на хэш-таблице.
-​ Не гарантирует порядок элементов.
-​ Основные операции (add(), remove(), contains()) выполняются за O(1) (в
среднем).
-​ Позволяет хранить null значение.
-​ Требует, чтобы объекты корректно переопределяли методы hashCode() и
equals().

пример TreeSet
-​ Гарантирует отсортированный порядок элементов.
-​ Основные операции (add(), remove(), contains()) выполняются за O(log
n).
-​ Не допускает null (начиная с Java 8).
-​ Элементы должны реализовывать интерфейс Comparable или передаваться
Comparator при создании.

27.​Очереди в Java, интерфейс Queue, PrioritiQueue. Структура,


основные методы.
Очередью в Java считается все, что наследует интерфейс Queue,
который в свою очередь расширяет Collection. Это значит, что с
очередями можно работать, как с коллекциями.

Очереди в Java работают по двум принципам: FIFO и LIFO.

FIFO — First In First Out, принцип обычной очереди (конечно, если нет
тех кому нужно “только спросить”), в котором первый элемент
попадает в очередь и первым выходит из нее.

LIFO — Last In First Out, принцип стека, в котором последний элемент,


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

Здесь видно, что у Queue есть 3 класса реализации: LinkedList,


ArrayDeque и PriorityQueue. LinkedList и ArrayDeque
наследует напрямую не от Queue, а от Deque.



основные методы Queue :

​ add(E e). Добавляет указанный элемент в очередь, возвращая true в


случае успеха и выдавая исключение IllegalStateException, если нет
свободного места.

​ element(). Получает, но не удаляет верхний элемент очереди. Если


очередь пуста, бросает исключение NoSuchElementException.

​ offer(E e). Вставляет указанный элемент в очередь, если это возможно


сделать не нарушая ограничений пропускной способности.

​ peek(). Получает, но не удаляет верхний элемент очереди или


возвращает null, если эта пуста.

​ poll(). Получает и удаляет верхний элемент очереди или возвращает null,


если эта пуста.

​ remove(). Удаляет верхний элемент очереди. Если очередь пуста,


бросает исключение NoSuchElementException.

Есть еще класс PriorityQueue, прямой наследник Queue: принцип


его работы отличается от наследников Dequeue.​

PriorityQueue — это очередь с приоритетом, которая по умолчанию
размещает элементы согласно естественному порядку сортировки.
Для сортировки здесь используется Comparable и Comparator.

Основные методы класса PriorityQueue:


​ add(E e). Добавляет элемент в PriorityQueue.

​ clear(). Очищает PriorityQueue, удаляя все элементы.

​ comparator(). Возвращает пользовательский компаратор, используемый


для упорядочивания элементов в очереди.

​ contains(Object o). Проверяет, присутствует ли данный элемент в


PriorityQueue. Если да, возвращает true.

​ iterator(). Возвращает итератор для данного PriorityQueue.


​ offer(E e). Вставляет указанный элемент в PriorityQueue.

​ peek(). Используется для возврата заголовка очереди без удаления


элемента.

​ poll(). Если очередь пуста, возвращает значение null, в противном


случае удаляет и возвращает начало очереди.

​ size(). Возвращает количество элементов в PriorityQueue.

28.​Байтовые потоки InputStream и OutputStream. Консольный ввод и


вывод Java. Символьные потоки данных. Абстрактные классы Writer,
Reader.

В Java для работы с вводом-выводом данных используются байтовые и


символьные потоки:
➢​Байтовые потоки работают с данными в виде байтов. Они подходят
для работы с бинарными файлами (например, изображения, видео).
➢​Символьные потоки работают с данными в виде символов. Они
используют кодировку и предназначены для работы с текстовыми
файлами.

Классы InputStream и OutputStream - абстрактные классы, которые


определяют базовые операции для чтения и записи байтов.
​ •​ InputStream - это класс в Java, предоставляющий возможность
чтения байтов из различных источников, таких как файлы или сетевые
соединения.

InputStream is = new FileInputStream("input.txt");


int byteData = is.read(); // Возможность читать данные на уровне байтов

​ •​ OutputStream - предназначен для записи байтов в разнообразные


приемники, будь то файлы или сетевые сокетых.
OutputStream os = new FileOutputStream("output.txt");
os.write(65); // Записываем символ 'A' в виде байта

Основные методы:
​ •​ int read() – читает один байт.
​ •​ int read(byte[] b) – читает массив байтов.
​ •​ void write(int b) – записывает один байт.
​ •​ void write(byte[] b) – записывает массив байтов.
​ •​ void close() – закрывает поток.

В Java консольный ввод-вывод осуществляется с использованием:


●​ System.in – стандартный ввод (InputStream).

○​ Для получения ввода с консоли в классе System определен


объект in. Однако непосредственно через объект System.in не
очень удобно работать, поэтому, как правило, используют
класс Scanner, который, в свою очередь использует System.in.

○​ Класс BufferedReader позволяет читать строки или символы


более эффективно (Он буферизует символы, чтобы можно
было эффективно считывать символы, массивы и т. д. Он
наследует класс чтения и делает код эффективным, поскольку
мы можем считывать данные построчно с помощью метода
readline()).

●​ System.out – стандартный вывод (OutputStream).

Для вывода данных на консоль используется System.out. Это поток типа


PrintStream, предоставляющий методы для вывода данных.
Основные методы:
​ •​ print(...) — вывод без переноса строки.
​ •​ println(...) — вывод с переносом строки.
​ •​ printf(String format, Object... args) — форматированный вывод.

Абстрактные классы Reader и Writer являются символьными потоками:​

Reader: обеспечивает поддержку символьного потока чтения аналогично


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

Writer: обеспечивает поддержку символьного потока записи аналогично


тому, как это делает OutputStream, реализующий модель байтового потока
вывода. Многие методы Writer схожи с теми, которые объявлены в
OutputStream; помимо этого, в классе Writer предусмотрены некоторые
другие полезные версии метода write.

29.​Чтение и запись файлов. Классы FileInputStream, FileOutputStream.


Файловый ввод-вывод с использованием символьных потоков.
Классы FileReader и FileWriter.
Чтение и запись файлов в Java реализуется с использованием классов
ввода-вывода (I/O).

Основные классы для работы с файлами:

1.​ FileInputStream и FileOutputStream — используются для


побайтового чтения и записи.

2.​ FileReader и FileWriter — используются для символьного


ввода-вывода.

Первые классы работают с потоками байтов, они являются наследниками


абстрактных классов InputStream & OutputStream, которые являются
суперклассами для реализаций чтения и записи в файлы.

FileInputStream и FileOutputStream подходят для работы с файлами,


содержащими данные в бинарном формате, например, изображениями,
аудио или видео (для текста тоже можно).

В конструкторе они принимают либо путь к целевому файлу, либо объект


класса File.
Хотя с помощью ранее рассмотренных классов можно записывать текст в
файлы, однако они предназначены прежде всего для работы с бинарными
потоками данных, и их возможностей для полноценной работы с
текстовыми файлами недостаточно. И для этой цели служат совсем другие
классы, которые являются наследниками абстрактных классов Reader и
Writer.

Классы FileReader и FileWriter работают с символьными потоками. Они


служат для работы с текстовыми файлами, обеспечивая поддержку работы
с символами и кодировками.

В конструктор передается либо путь к файлу в виде строки, либо объект


File, который ссылается на конкретный текстовый файл. Параметр append
указывает, должны ли данные дозаписываться в конец файла
30.​Многопоточное программирование: общие принципы.
Поток — это независимая последовательность выполнения, которая может
выполняться параллельно с другими потоками. Каждый поток имеет свой
собственный стек, регистры и локальные переменные, но может разделять
память с другими потоками.

Выполнение нескольких потоков в рамках одного процесса или


приложения.

Каждый поток имеет собственный счётчик программ, стек и локальные


данные, но разделяет пространство памяти, глобальные данные и
системные ресурсы с другими потоками в том же процессе.
•​ Параллельное выполнение задач. Например, один поток может
обрабатывать данные, в то время как другой выводит информацию на
экран. Эти действия независимы друг от друга и могут выполняться
параллельно

•​ Грамотное распределение ресурсов. В многозадачных системах


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

•​ Синхронизация потоков. Она нужна, чтобы избежать конфликтов


при доступе к общим ресурсам. Для этого используются механизмы
синхронизации, такие как мьютексы и семафоры.

Java предоставляет класс Thread для управления потоками, который


позволяет:

-​ Запускать поток: start()

-​ Приостанавливать поток: sleep(milliseconds)

-​ Ожидать завершения потока: join()

-​ Проверять состояние потока: isAlive()

31.​Класс Thread и интерфейс Runnable: создание потоков, приоритеты


потоков.
https://java-online.ru/java-thread.xhtml

В Java для работы с потоками используются класс Thread и интерфейс


Runnable, которые позволяют выполнять несколько задач одновременно
(многопоточность).

Создание потоков:
1. Наследование от класса Thread
Класс Thread представляет собой поток выполнения. Для создания потока
можно унаследоваться от этого класса и переопределить его метод run(), в
котором описывается логика выполнения:
class MyThread extends Thread {​
​ @Override​
​ public void run() {​
​ ​ System.out.println("Thread is running...");​
​ }​
}

public class Main {​


​ public static void main(String[] args) {​
​ ​ MyThread thread = new MyThread();​
​ ​ thread.start(); // запуск потока​
​ }​
}

Важно: Метод start() вызывает системный код, который запускает поток и


вызывает его метод run(). Если вызвать run() напрямую, код выполнится в
основном потоке, а не в новом.

2. Реализация интерфейса Runnable


Интерфейс Runnable позволяет создавать потоки без наследования от
класса Thread. Это особенно полезно, если класс уже наследуется от
другого класса:

class MyRunnable implements Runnable {​


​ @Override​
​ public void run() {​
​ ​ System.out.println("Thread is running...");​
​ }​
}

public class Main {​


​ public static void main(String[] args) {​
​ ​ MyRunnable runnable = new MyRunnable();​
​ ​ Thread thread = new Thread(runnable);​
​ ​ thread.start(); // запуск потока​
​ }​
}

Отличие: Наследование от Thread жестко связывает логику потока с


классом, тогда как использование Runnable позволяет отделить поток
выполнения от его логики. Кроме того, Java не поддерживает
множественное наследование, поэтому Runnable гибче.

Приоритеты потоков
У каждого потока в Java есть приоритет, который влияет на порядок его
выполнения. Приоритеты задаются числом от 1 до 10, где:

●​ Thread.MIN_PRIORITY = 1 (минимальный приоритет),

●​ Thread.NORM_PRIORITY = 5 (нормальный приоритет, значение по


умолчанию),
●​ Thread.MAX_PRIORITY = 10 (максимальный приоритет).

Пример установки приоритета:

Thread thread = new Thread(() -> System.out.println("Thread is running..."));

thread.setPriority(Thread.MAX_PRIORITY); // Устанавливаем
максимальный приоритет

thread.start();

Особенности:

●​ Поток с более высоким приоритетом имеет больше шансов получить


процессорное время.

●​ Приоритеты потоков зависят от реализации JVM (Java Virtual


Machine) и операционной системы, поэтому их влияние не
гарантируется.

Основные методы класса Thread:


1) start() — запускает поток. Вызывает метод run() в новом потоке.​
2) run() — содержит код, который выполняется в потоке.​
3) sleep(long millis) — приостанавливает выполнение потока на
указанное время (в миллисекундах).​
4) join() — заставляет текущий поток дождаться завершения другого.​
5) setPriority(int priority) — задает приоритет потока.​
6) isAlive() — проверяет, выполняется ли поток в данный момент.
32.​Приостановка и прерывание потоков. Определение момента
завершения потока.​

Приостановка потока
В современном Java не рекомендуется использовать устаревшие методы вроде
suspend() и resume() (они были убраны из-за потенциальных проблем с
безопасностью). Вместо этого для приостановки потока можно использовать
метод сна (sleep()), механизм ожидания (wait()) или управляющий флаг.

Использование метода сна:

●​ Поток засыпает на заданное время, освобождая процессор.


Thread.sleep(1000); // Поток "уснет" на 1 секунду

Использование механизма ожидания:

●​ Методы wait() и notify() - поток "ждет", пока другой поток или событие
снимет блокировку.

Флаги или сигналы:

●​ Программист может самостоятельно реализовать логику приостановки,


например, с помощью переменных-флагов.

●​ Поток проверяет значение флага и "останавливается", если это


необходимо.

Прерывание потоков
Прерывание используется для сигнализации потоку о том, что он должен
завершить свою работу. Метод interrupt() не останавливает поток немедленно, а
подаёт сигнал (выставляет флаг прерывания), что поток должен остановиться.
Поток может обработать этот сигнал и завершить работу.

Как работает interrupt():


●​ Если поток находится в состоянии ожидания или сна (sleep(), wait()), он
выбрасывает исключение InterruptedException.

●​ Если поток не находится в этих состояниях, флаг прерывания будет


установлен, и проверяется с помощью метода
Thread.currentThread().isInterrupted().

Определение завершения потока


Чтобы определить, завершился ли поток, используется метод isAlive() или
можно дождаться его завершения с помощью join().
Что делает join():
●​ Ожидает завершения потока, прежде чем продолжить выполнение кода в
основном потоке.

●​ Можно передать таймаут, чтобы ждать ограниченное время:


thread.join(3000).
33.​Синхронизация потоков.
Синхронизация потоков - это настройка взаимодействия потоков между
собой. Несколько потоков могут активно работать, например, с одним и
тем же набором данных и что-то в нем менять. Это создает проблемы.

Представь, что несколько потоков записывают текст в одно и то же место


— например, в текстовый файл или консоль.

Этот файл или консоль в данном случае становится общим ресурсом.


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

Поэтому в многопоточном программировании ввели специальное понятие


мьютекс (от англ. «mutex», «mutual exclusion» — «взаимное исключение»).

Задача мьютекса — обеспечить такой механизм, чтобы доступ к объекту в


определенное время был только у одного потока. Если Поток-1 захватил
мьютекс объекта А, остальные потоки не получат к нему доступ, чтобы
что-то в нем менять. До тех пор, пока мьютекс объекта А не освободится,
остальные потоки будут вынуждены ждать.

В Java синхронизация реализуется с помощью ключевого слова


synchronized, которое может быть применено:

●​ К методам.
●​ К блокам кода.
public synchronized void doSomething() {

public class Main {

private Object obj = new Object();


public void doSomething() {

synchronized (obj) {

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

Эти два способа записи означают одно и то же:


public void swap() {

synchronized (this)

public synchronized void swap() {

}
}

34.​Архитектура JDBC (Java DataBase Connectivity). Двух и


трехуровневые модели доступа к базе данных. Преимущества и
недостатки JDBC.

35.​Библиотека Swing, общие черты и особенности.


Swing — это библиотека для создания графического пользовательского
интерфейса (GUI) на языке Java. Она является частью Java Foundation Classes
(JFC) и предоставляет мощный и гибкий инструментарий для создания
приложений с современным дизайном и функциональностью. Swing работает
поверх более базовой библиотеки AWT (Abstract Window Toolkit), предлагая
расширенные возможности и независимость от платформы.
Общие черты

●​ Кросс-платформенность: Swing-компоненты написаны на Java, благодаря


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

●​ Широкий набор компонентов: Swing предоставляет множество


стандартных компонентов, таких как кнопки (JButton), текстовые поля
(JTextField), таблицы (JTable), деревья (JTree) и вкладки (JTabbedPane),
что позволяет создавать как простые, так и сложные пользовательские
интерфейсы.

●​ Модель MVC: Архитектура Swing основана на принципе


«Модель-Вид-Контроллер» (MVC), что обеспечивает разделение логики
данных, их отображения и управления, упрощая разработку и поддержку
кода.

●​ Поддержка событий: Swing реализует мощную модель событий,


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

●​ Гибкость и настраиваемость: Компоненты Swing легко кастомизируются,


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

Особенности:

●​ Легковесные компоненты: Компоненты Swing являются легковесными,


так как не зависят напрямую от графической системы операционной
системы, а полностью реализованы средствами Java.

●​ Двойная буферизация: Swing использует двойную буферизацию для


рендеринга графики, что исключает мерцание и делает интерфейс более
плавным.

●​ Многоуровневая архитектура компоновки: Swing поддерживает


вложенные панели и менеджеры компоновки (FlowLayout, BorderLayout,
GridLayout), позволяя создавать сложные и гибкие графические
интерфейсы.

●​ Look and Feel: Swing предоставляет возможность изменять стиль и


внешний вид компонентов, используя предустановленные стили (Metal,
Nimbus, Windows, и другие) или создавая собственные.
●​ Поддержка графики и анимации: Swing позволяет рисовать собственные
компоненты и обрабатывать графику, обеспечивая поддержку сложных
пользовательских элементов и анимации.

●​ Поддержка сложных интерфейсов: Swing предоставляет компоненты для


работы с табличными данными (JTable), иерархическими структурами
(JTree), вкладками (JTabbedPane) и другими сложными элементами
интерфейса.

36.​Виды контейнеров в Swing.


1. JFrame

JFrame — это основной контейнер для создания оконных приложений. Он

представляет собой главное окно приложения и может содержать другие


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

Пример создания JFrame:

2. JPanel

JPanel — это универсальный контейнер, который может содержать другие

компоненты. Он часто используется для группировки компонентов и


управления их расположением. JPanel может использовать различные
менеджеры компоновки для определения расположения своих дочерних
компонентов.
Пример использования JPanel:

3. JScrollPane

JScrollPane — это контейнер, который добавляет возможность прокрутки к

другим компонентам, таким как JPanel или JTextArea. Он автоматически


добавляет полосы прокрутки, если содержимое превышает размеры видимой
области.

Пример использования JScrollPane:

4. JTabbedPane

JTabbedPane — это контейнер, который позволяет организовать компоненты в

виде вкладок. Каждая вкладка может содержать разные компоненты, и


пользователь может переключаться между ними.

Пример использования JTabbedPane:


5. JToolBar

JToolBar — это контейнер, который используется для размещения кнопок

инструментов и других элементов управления. Он обычно располагается в


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

Пример использования JToolBar:

6. JLayeredPane

JLayeredPane — это контейнер, который позволяет размещать компоненты на

разных уровнях (слоях). Это полезно для создания сложных интерфейсов, где
компоненты могут перекрывать друг друга.

Пример использования JLayeredPane:

7. JSplitPane

JSplitPane — это контейнер, который позволяет разделить область на две

части, которые могут быть изменены по размеру. Это полезно для создания
интерфейсов с изменяемыми панелями.
Пример использования JSplitPane:

37.​Элементы пользовательского интерфейса Swing.

Категория Компоненты Пример кода

Основные JFrame – главное java JFrame frame = new JFrame("Пример JFrame");


контейнеры окно приложения frame.setSize(400, 300);
JDialog – frame.setDefaultCloseOperation(JFrame.EXIT_ON_C
диалоговое окно LOSE); frame.setVisible(true);
JWindow – окно без
рамки

Контейнеры JPanel – панель java JPanel panel = new JPanel(); panel.add(new


для для группировки JButton("Кнопка")); frame.add(panel);
компоновки компонентов
JScrollPane –
панель с прокруткой
JTabbedPane –
вкладки для
отображения
панелей

Элементы JButton – кнопка java JButton button = new JButton("Нажми меня");


управления JTextField – button.addActionListener(e ->
однострочное JOptionPane.showMessageDialog(null, "Кнопка
текстовое поле нажата!")); frame.add(button);
JTextArea –
многострочное
текстовое поле
JComboBox –
выпадающий
список
Элементы JLabel – java JLabel label = new JLabel("Привет, Swing!");
отображения текст/изображение frame.add(label);
JProgressBar –
индикатор
выполнения
JToolTip –
всплывающая
подсказка

Меню и JMenuBar – java JMenuBar menuBar = new JMenuBar(); JMenu


панели главное меню menu = new JMenu("Файл"); menu.add(new
инструментов JToolBar – панель JMenuItem("Открыть")); menuBar.add(menu);
инструментов frame.setJMenuBar(menuBar);

Диалоговые JOptionPane – java JOptionPane.showMessageDialog(null, "Это


окна диалоговое окно с сообщение!");
сообщением
JFileChooser –
диалог для выбора
файлов
JColorChooser –
диалог для выбора
цвета

Таблицы JTable – таблица java String[][] data = {{"1", "Иван"}, {"2", "Мария"}};
данных String[] columns = {"ID", "Имя"}; JTable table = new
JTable(data, columns); frame.add(new
JScrollPane(table));

Менеджеры FlowLayout – слева java frame.setLayout(new FlowLayout());


компоновки направо frame.add(new JButton("Кнопка 1")); frame.add(new
BorderLayout – 5 JButton("Кнопка 2"));
зон (NORTH,
SOUTH и т. д.)
GridLayout –
таблица
BoxLayout –
вертикальное/гориз
онтальное
выравнивание
38.​Модель событий Swing. Интерфейс EventListener.
Модель событий Swing в Java основана на концепции делегирования обработки
событий (event delegation model). Это означает, что источник события
(например, кнопка или другой графический компонент) генерирует событие, а
обработка события делегируется одному или нескольким слушателям.

Основные аспекты модели событий

1.​ Источник событий (Event Source)​


Источником событий является компонент, который генерирует события,
такие как щелчки мыши, нажатия клавиш или действия пользователя.
Примеры: кнопки (JButton), текстовые поля (JTextField), окна
(JFrame).

2.​ События (Event Object)​


Событие — это объект, который содержит информацию о том, что
произошло. В Java класс события наследуется от
java.util.EventObject. В Swing используются такие подклассы, как:

○​ ActionEvent — для событий действий (например, нажатие


кнопки).

○​ MouseEvent — для событий мыши.

○​ KeyEvent — для событий клавиатуры.

○​ WindowEvent — для событий окна.

3.​ Слушатель событий (Event Listener)​


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

○​ ActionListener — интерфейс для обработки событий действия


(ActionEvent).

○​ MouseListener — интерфейс для обработки событий мыши.

○​ KeyListener — интерфейс для обработки событий клавиатуры.

4.​ Регистрация слушателей (Listener Registration)​


Для того чтобы слушатель мог обрабатывать события от источника, его
нужно зарегистрировать через метод addXXXListener. Например:
○​ addActionListener(ActionListener l) — для событий
действия.

○​ addMouseListener(MouseListener l) — для событий мыши.


Интерфейс EventListener

EventListener — это маркерный интерфейс (без методов), который лежит в


основе всех слушателей событий в Java. Все интерфейсы слушателей
(например, ActionListener, MouseListener) расширяют этот интерфейс.

Ключевые моменты

1.​ Обработчик событий — это класс, который реализует интерфейс


слушателя.

2.​ Один источник события может иметь несколько слушателей.

3.​ Модель событий Swing инкапсулирует сложность обработки


пользовательского ввода.

Не уверен, что это нужно, но мало ли


39.​Менеджеры компоновки Swing.

В Swing менеджеры компоновки (layout managers) используются для


управления расположением компонентов внутри контейнеров. Каждый
контейнер в Swing (например, JPanel, JFrame) имеет свой менеджер
компоновки, который определяет, как размещать и изменять размеры
компонентов.

Основные менеджеры компоновки

●​ Полярное расположение BorderLayout: Разделяет контейнер на 5 зон


- North, South, East, West и Center. Каждая зона может содержать
только один компонент.

●​ Последовательное расположение FlowLayout: Располагает


компоненты в одну строку, перенося их на следующую строку, если
не хватает места.

●​ Табличное расположение GridLayout: Разбивает контейнер на сетку


с фиксированным числом строк и столбцов. Все ячейки имеют
одинаковый размер.

●​ Менеджер расположения GridBagLayout: Один из самых гибких, но


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

●​ Менеджер расположения CardLayout: Позволяет переключаться


между “карточками” (различными наборами компонентов).

●​ Менеджер расположения BoxLayout: Располагает компоненты в одну


строку (по горизонтали) или в один столбец (по вертикали).

Поддержка менеджеров расположения встроена в базовый класс


контейнеров java.awt.Container. Все компоненты библиотеки Swing
унаследованы от базового класса JComponent, который, в свою очередь,
унаследован от класса Container. Таким образом, для любого компонента
Swing можно установить менеджер расположения или узнать, какой
менеджер им используется в данный момент. Для этого предназначены
методы setLayout() и getLayout().
Управлять расположением компонентов желательно с помощью тех
инструментов, которые специально для этого служат. Самый
распространённый из них это — JPanel, мы не раз его использовали. Также
следует помнить, что в виду изменения содержимого одного из
компонентов, ему может перестать хватать прежних размеров. Или,
наоборот, прежний размер для них будет чрезмерно велик. Проверку
корректности габаритов для каждого компонента позволяет выполнить
метод revalidate().

40.​GUI Designer Swing

GUI Designer Swing – это инструмент для разработки графических


пользовательских интерфейсов (GUI) на платформе Java с использованием
библиотеки Swing. Этот инструмент упрощает процесс создания
интерфейсов и минимизирует объем ручного кода, который необходимо
написать.

Основные особенности:

●​ Вы видите интерфейс таким, каким он будет в реальном


приложении, уже на этапе проектирования.

●​ GUI Designer предоставляет удобный способ работы с менеджерами


компоновки (Layout Managers), такими как:

○​ GridBagLayout

○​ BorderLayout

○​ FlowLayout

○​ BoxLayout и другие.

●​ Позволяет перетаскивать визуальные компоненты (кнопки, поля


ввода, панели, метки и т. д.) из панели инструментов на рабочую
область.
●​ После создания интерфейса в дизайнере автоматически генерируется
код Java, который можно использовать в вашем проекте.

●​ Часто используется в интегрированных средах разработки


(например, IntelliJ IDEA или NetBeans).

●​ Легко добавляются слушатели событий (ActionListener,


MouseListener и т. д.) для обработки пользовательских действий.

Пример:

Допустим, вы используете GUI Designer в IntelliJ IDEA:

1.​ Вы создаете новую форму (.form) и добавляете на нее элементы


интерфейса.

2.​ Среда автоматически генерирует код, например:

private JPanel mainPanel;

private JButton buttonOK;

private JTextField textField;

public MyForm() {

buttonOK.addActionListener(e -> JOptionPane.showMessageDialog(null,


"Нажата кнопка!"));

public static void main(String[] args) {

JFrame frame = new JFrame("MyForm");

frame.setContentPane(new MyForm().mainPanel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

frame.pack();

frame.setVisible(true);

41.​Текстовые поля в Swing


Swing в Java — это инструментарий с графическим интерфейсом, который
имеет широкий спектр виджетов для создания оптимизированных оконных
приложений.

Текстовое поле в Swing— это компонент графического интерфейса,


который позволяет пользователям вводить текст. Для создания и
управления текстовыми полями в Swing используется класс JTextField
(однострочный текст).

Для создания текстового поля чаще всего используются конструкторы:

· ​ JTextField(int columns) — создаёт пустое текстовое поле, ширина


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

· ​ JTextField(String text) — создаёт текстовое поле с начальным текстом


text.

· ​ JTextField(String text, int columns) — устанавливает и ширину, и


начальный текст.

Некоторые методы класса JTextField для работы с текстовыми полями:

· ​ setText(String text) — устанавливает текст, отображаемый в текстовом


поле, на указанное значение.
· ​ getText() — возвращает текущий текст, введённый пользователем в
текстовом поле.

· ​ setColumns(int columns) — устанавливает предпочитаемое количество


столбцов (ширину) текстового поля.

· ​ addActionListener(ActionListener listener) — добавляет к текстовому


полю ActionListener. Слушатель будет уведомлён, когда пользователь
нажмёт клавишу «Enter», часто сигнализирующую об окончании ввода
пользователя.

Текстовое поле JPasswordField, унаследованное от поля JTextField, дает


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

Существует также многострочное текстовое поле JTextArea. Оно


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

Для многострочных полей необходимо задавать не только ширину


(максимальное количество символов), но и высоту (максимальное
количество строк).

42.​Компонент управления JButton в Swing


JButton — это класс в библиотеке Swing, который представляет кнопку
для пользовательского интерфейса. Она используется для выполнения
определенного действия при нажатии.

Создание JButton

Для создания кнопки используется ее конструктор. Можно задать текст,


иконку или оставить кнопку пустой:

JButton button = new JButton("Нажми меня"); // Кнопка с текстом​


frame.add(button);

Обработка событий
Чтобы обработать нажатие кнопки, используется интерфейс
ActionListener. Он позволяет выполнить код при нажатии:

button.addActionListener(e -> System.out.println("Кнопка нажата!"));

Пример:

JButton button = new JButton("Нажми меня");​


button.addActionListener(new ActionListener() {​
​ @Override​
​ public void actionPerformed(ActionEvent e) {​
​ ​ JOptionPane.showMessageDialog(frame, "Кнопка была
нажата!");​
​ }​
});

frame.add(button)

Основные методы JButton


1) Установка текста и иконки:​

button.setText("Новый текст");​
button.setIcon(new ImageIcon("path/to/icon.png"));

2) Изменение состояния:

setEnabled(boolean enabled) — включить/выключить кнопку.​


​ isEnabled() — проверяет, активна ли кнопка.

3) Изменение цвета и шрифта:​



button.setBackground(Color.BLUE);​
button.setForeground(Color.WHITE);​
button.setFont(new Font("Arial", Font.BOLD, 14));

Особенности и преимущества JButton


1) Гибкость: можно настроить текст, цвет, иконку и поведение кнопки.​
2) Поддержка событий: легко обработать действия с помощью
ActionListener.​
3) Доступные состояния: кнопка может быть включена, выключена или
скрыта.
43.​Платформа JavaFX, особенности, компоненты
JavaFX — это современная библиотека для создания графических
пользовательских интерфейсов (GUI) в Java. Она была разработана как замена
устаревшей библиотеки Swing. JavaFX предоставляет мощные инструменты для
разработки настольных, мобильных и веб-приложений.
Особенности JavaFX

●​ Кроссплатформенность: JavaFX поддерживает работу на всех основных


операционных системах (Windows, macOS, Linux)

●​ Гибкая разметка интерфейсов: Поддерживает CSS для стилизации


компонентов. Использует FXML — XML-нотацию для описания
интерфейсов.
●​ Интеграция с современными технологиями: Легко связывается с
базами данных, REST API и веб-сервисами. Поддержка видеоконтента
(через Media и MediaView). Поддержка 3D-графики.
●​ Поддержка MVC (Model-View-Controller): Легко реализовать
архитектурный подход MVC для четкого разделения логики, данных и
представления.
Основные компоненты JavaFX
Структура приложения: Приложение начинается с класса, наследующего
javafx.application.Application. Основной метод start(Stage primaryStage)
определяет главный интерфейс.

Stage: Представляет "главное окно" приложения. В каждом JavaFX-приложении


есть хотя бы один объект Stage.(import javafx.stage.Stage;)

Scene: Scene отображает содержание сцены (stage). Каждая компонента stage


может содержать несколько компонент scene, которые можно переключать.
(import javafx.scene.Scene;)​

Node: Каждая компонента stage может содержать различные компоненты,
называемые узлами (node). Узлы могут быть элементами управления, такими
как кнопки или метки, или даже макетами иногда их называют контейнерами
(layout), которые могут содержать несколько вложенных компонентов. Каждая
сцена (scene) может иметь один вложенный узел (node), но это может быть макет
(layout), который может содержать несколько компонентов. Вложенность может
быть многоуровневой — макеты могут содержать другие макеты и обычные
компоненты.​

Визуализация иерархии:​

44.​Шаблон MVC (Model-View-Controller) в Spring.

MVC (Model–View–Controller) – это архитектурно/проектный


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

Контроллер — это компонент, позволяющий соединять представления и


модель, следовательно, он выступает в качестве посредника. Он отвечает
за всю бизнес–логику и входящие запросы – получение информации от
пользователя и ее интерпретация, обработка данных и обновление модели
на основе действий пользователей и взаимодействие с View для получения
конечного результата.

Модель – это компонент, позволяющий осуществить передачу данных, с


которыми работает пользователь. Модель отвечает на запрос контроллера
(так как контроллер самостоятельно не взаимодействует с базой),
осуществляет различные операции с данными (CRUD – Create, Read,
Update, Delete) и возвращает необходимые данные обратно.

Представление – задействовано в реализации всей логики


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

45.​Классы StringBuffer и StringBuilder.


StringBuffer и StringBuilder — классы для работы со строками в Java, которые
создают изменяемый набор символов.
●​ StringBuffer
изменяемый и потокобезопасный благодаря синхронизации, но менее
эффективный, чем StringBuilder, с точки зрения производительности.
Лучше использовать в многопоточной среде.

●​ StringBuilder
изменяемый, не потокобезопасный и более экономичный по сравнению
со String. Лучше всего использовать для однопоточных операций.

Классы StringBuilder и StringBuffer предоставляют важные методы, которых не


предоставляет класс String, такие как insert(), delete() и reverse().

46.​Архитектура JDBC (Java DataBase Connectivity). Двух и


трехуровневые модели доступа к базе данных. Преимущества и
недостатки JDBC.
JDBC (Java DataBase Connectivity) - интерфейс, который позволяет
программистам соединяться с базой данных, запрашивать и обновлять данные с
помощью языка структурированных запросов (SQL).

Архитектура JDBC состоит из двухуровневых и трехуровневых моделей


обработки для доступа к базе данных.

Двухуровневая архитектура
Приложение Java взаимодействует напрямую с базой данных с помощью
драйвера JDBC. Запросы отправляются в базу данных, а результаты
возвращаются непосредственно приложению. При настройке клиент / сервер
компьютер пользователя (клиент) взаимодействует с удаленным сервером базы
данных.

Структура:

Клиентское приложение (Java) -> Драйвер JDBC -> База данных

Трехуровневая архитектура

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


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

Структура:

Клиентское приложение -> Сервер приложений -> Драйвер JDBC -> База
данных

Преимущества JDBC

●​ Прямой контроль и выполнение: JDBC позволяет разработчикам


управлять SQL-запросами и оптимизировать их для конкретных задач.

●​ Совместимость: JDBC поддерживает все основные СУБД, что


обеспечивает универсальность.

●​ Гибкость: Разработчики могут напрямую использовать SQL, что


упрощает работу с нестандартными запросами.

●​ Легкость интеграции: JDBC не требует дополнительных библиотек, что


упрощает архитектуру приложения.

Недостатки JDBC:

●​ Трудоемкость разработки: Работа с JDBC часто требует написания


повторяющегося кода для управления соединениями, исключениями и
обработкой данных.
●​ Объектно-реляционное несоответствие: Преобразование данных между
объектами Java и реляционными таблицами может быть сложным и
затратным.

●​ Отсутствие автоматизации: JDBC не предоставляет встроенных средств


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

47.​Массивы Java: объявление, инициализация. Основные методы класса


Arrays. Доступ к элементам массивов, итерация массивов.
Двумерные массивы.
Объявление и инициализация массивов

Объявление массива

Чтобы объявить массив в Java, необходимо указать тип элементов массива и


использовать квадратные скобки. Пример:

1int[] numbers; // Объявление массива целых чисел

2String[] names; // Объявление массива строк

Инициализация массива

Инициализация массива может быть выполнена несколькими способами:

●​ Инициализация с указанием размера:

●​ 1int[] numbers = new int[5]; // Создание массива на 5 элементов

●​ Инициализация с указанием значений:

●​ 1int[] numbers = {1, 2, 3, 4, 5}; // Создание и инициализация


массива

●​ Инициализация с использованием оператора new:

●​ 1String[] names = new String[]{"Alice", "Bob", "Charlie"}; //


Создание и инициализация массива строк
Основные методы класса Arrays

Класс java.util.Arrays предоставляет множество статических методов для


работы с массивами. Вот некоторые из них:

●​ Arrays.sort(array): сортирует массив.

●​ Arrays.copyOf(original, newLength): создает новый массив, копируя


элементы из оригинального массива.

●​ Arrays.equals(array1, array2): сравнивает два массива на равенство.

●​ Arrays.toString(array): возвращает строковое представление массива.

●​ Arrays.fill(array, value): заполняет массив указанным значением.

Доступ к элементам массивов

Доступ к элементам массива осуществляется с помощью индексов. Индексация


начинается с нуля, то есть первый элемент имеет индекс 0, второй — 1 и так
далее.

Итерация по массивам

Итерация по массивам может быть выполнена с использованием цикла for,


for-each или while.

Цикл for:

1for (int i = 0; i < numbers.length; i++) {

2 System.out.println(numbers[i]);

3}

Цикл for-each:

1for (int number : numbers) {


2 System.out.println(number);

3}

Цикл while:

1int i = 0;

2while (i < numbers.length) {

3 System.out.println(numbers[i]);

4 i++;

5}

Двумерные массивы

Двумерные массивы представляют собой массив массивов. Они могут быть


использованы для представления таблиц или матриц.

Объявление и инициализация двумерного массива

1int[][] matrix = new int[3][4]; // Создание двумерного массива 3x4

Или с инициализацией значений:

1int[][] matrix = {

2 {1, 2, 3, 4},

3 {5, 6, 7, 8},

4 {9, 10, 11, 12}

5};

Доступ к элементам двумерного массива

Доступ к элементам двумерного массива осуществляется с помощью двух


индексов:
1int element = matrix[1][2]; // Доступ к элементу в строке 1 и столбце 2
(значение 7)

Итерация по двумерным массивам

Итерация по двумерным массивам может быть выполнена с использованием


вложенных циклов:

1for (int i = 0; i < matrix.length; i++) {

2 for (int j = 0; j < matrix[i].length; j++) {

3 System.out.print(matrix[i][j] + " ");

4 }

5 System.out.println(); // Переход на новую строку после каждой строки


матрицы

6}

48.​Иерархия наследования Java. Преобразование типов при


наследовании. Ключевое слово instanceof.

Один класс наследует свойства и методы другого. Все классы наследуются от Object,
если не указан другой родитель. Типы: одноуровневое, многоуровневое, интерфейсы,
абстрактные классы.

java class Animal { void makeSound() { System.out.println("Звук"); } }

class Dog extends Animal { void bark() { System.out.println("Лай"); } }

Puppy p = new Puppy(); p.makeSound(); p.bark();

преобразование типов

Upcasting (восходящее преобразование): от подкласса к суперклассу, безопасно.


Downcasting (нисходящее преобразование): от суперкласса к подклассу, требует
явного приведения.

Оператор instanceof

Проверяет, принадлежит ли объект к классу или его подклассу. Используется для


безопасного нисходящего приведения.

java Animal a = new Dog();


if (a instanceof Dog) { ((Dog) a).bark(); }

пример

java ArrayList<Animal> animals = new ArrayList<>();

animals.add(new Dog());

for (Animal a : animals) { if (a instanceof Dog) ((Dog) a).bark(); }

49.​Интерфейсы Java: определение интерфейса, реализация интерфейса.


Преимущества применения интерфейсов. Переменные интерфейсов.
Наследование интерфейсов. Методы по умолчанию. Статические
методы интерфейсов.
Интерфейсы в Java — это абстрактные типы, которые определяют набор методов, но
не предоставляют их реализацию. Они используются для обеспечения контракта,
который обязуются выполнять классы, реализующие эти интерфейсы.

Реализация интерфейса

Класс, реализующий интерфейс, обязан предоставить реализацию всех его методов,


если он сам не является абстрактным.
Преимущества применения интерфейсов

Множественное наследование​
Класс в Java может реализовывать несколько интерфейсов, что позволяет достичь
множественного наследования, которого нет в наследовании классов.

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

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

Контракт на реализацию​
Интерфейсы гарантируют, что все классы, их реализующие, будут иметь
определённый набор методов.

Переменные интерфейсов

●​ Все переменные интерфейсов:


○​ Неизменяемые (final) — значение задаётся при объявлении.
○​ Неявно public static final, то есть являются константами.

Наследование интерфейсов

Интерфейсы могут наследоваться от других интерфейсов с использованием ключевого


слова extends. Интерфейс может наследовать несколько других интерфейсов.
Методы по умолчанию в интерфейсах

В Java 8 были добавлены методы по умолчанию (default methods), которые


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

С версии Java 8 интерфейсы могут содержать статические методы. Эти методы не


наследуются классами, а вызываются через имя интерфейса.
Ключевые моменты

Абстракция: Интерфейсы позволяют определить контракт, не включая детали


реализации.

Множественное наследование: Класс может реализовать несколько интерфейсов.

Методы по умолчанию: Предоставляют реализацию метода внутри интерфейса


(начиная с Java 8).

Статические методы: Интерфейсы могут иметь методы, которые вызываются через


имя интерфейса.

Константы: Все переменные интерфейса — это публичные, статические и финальные


константы.

50.​Байтовые потоки InputStream и OutputStream. Консольный ввод и


вывод Java. Символьные потоки данных. Абстрактные классы Writer,
Reader. - это вопрос 28
51.​Основные фреймворки и задачи, решаемые Spring.
Spring для Java — обширная платформа для создания веб-проектов на
Java, состоящая из множества независимых модулей (проектов) для разных
задач: от простых веб-приложений до Big Data.
Spring состоит из большого числа модулей. Среди них есть
модули-стартеры, без которых Spring-приложение просто не запустится, а
есть также вспомогательные проекты, добавляющие в приложение
определённую функциональность.

Spring Framework — ядро платформы Spring. Framework неявно


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

Spring Framework включает(думаю можно не писать):

●​ Основные технологии: внедрение зависимостей, события, ресурсы,


i18n, проверка, связывание данных, преобразование типов, SpEL,
AOP.

●​ Инструменты тестирования: mock-объекты, TestContext, Spring MVC


Test, WebTestClient.

●​ Доступ к данным: транзакции, поддержка DAO, JDBC, ORM,


Marshalling XML.

●​ Интеграцию: удалённое взаимодействие, JMS, JCA, JMX,


электронная почта, задачи, планирование, кеш.

Основные модули и фреймворки Spring:

●​ Spring Boot — комплексный фреймворк для создания и запуска


приложений с минимальными усилиями и настройками. Этот модуль
делится на два стека: основанный на API сервлетов Spring MVC и
реактивный Spring WebFlux.

○​ Spring WebFlux — веб-платформа, созданная, чтобы по


максимуму использовать преимущества современных
многоядерных процессоров и обрабатывать огромное
количество одновременных подключений.
○​ Spring MVC построен на API сервлетов и использует
архитектуру синхронного блокирующего ввода-вывода с
моделью «один запрос на поток».

Характеристики

1.​ Готовые стартовые зависимости, упрощающие конфигурацию


сборки.

2.​ Возможность сконфигурировать проект прямо в браузере с


помощью Spring Initializr.

3.​ Автоматическая настройка сторонних библиотек (по


возможности).

4.​ Готовые к работе функции, такие как сбор метрик, проверка


работоспособности и использование внешней конфигурации.

5.​ Нет кодогенерации и не требуется конфигурация XML — всё


конфигурируется через аннотации.

●​ Spring Data — модуль обеспечивает приложениям доступ к данным


через реляционные и нереляционные базы данных (БД), map-reduce
фреймворки и облачные сервисы. Spring Data содержит множество
подпроектов, предназначенных для определённых СУБД.

Основной механизм, реализуемый в Spring Data — репозиторий.


Это набор интерфейсов, использующих JPA Entity для
взаимодействия с данными.

Характеристики

1.​ Настраиваемое отображение сущностей в БД на Java-объекты.

2.​ Создание динамических запросов в базу данных через


сигнатуру метода интерфейса репозитория.

3.​ Базовые классы для различных задач.

4.​ Прозрачный аудит объектов.

5.​ Возможность интегрировать собственный код репозитория.


6.​ Простая интеграция со Spring через JavaConfig, а также
кастомных пространств имён XML.

7.​ Расширенная интеграция с контроллерами Spring MVC.

●​ Spring Security — среда аутентификации, авторизации и контроля


доступа. Это стандартный фреймворк, который используется для
защиты приложений на основе Spring.

Spring Security предоставляет базовые функции безопасности,


которые можно легко расширить для ваших собственных нужд.

Характеристики

1.​ Аутентификация и авторизация пользователей.

2.​ Защита от атак, таких как фиксация сессии, кликджекинг,


подделка межсайтовых запросов и так далее.

3.​ Возможность интеграции с Servlet API.

4.​ Опционально подключаемый модуль Spring Web MVC.

●​ Со Spring Cloud вы сможете легко и быстро создавать шаблоны в


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

Шаблоны, созданные с помощью Spring Cloud, будут хорошо


работать в любой распределённой среде, включая ваш собственный
ноутбук, центры обработки данных и PaaS-платформы, такие как
Cloud Foundry.

Spring Cloud также состоит из множества подпроектов для разных


целей. Так, Spring Cloud Azure интегрирует Spring со службами
Azure, Spring Cloud Stream используется для создания управляемых
событиями микросервисов (event-driven microservices) и так далее.

Характеристики

1.​ Распределённая / версионная конфигурация.

2.​ Регистрация и обнаружение сервисов.


3.​ Маршрутизация.

4.​ Связь между сервисами (service-to-service calls).

5.​ Балансировка нагрузки.

6.​ Выбор лидера и состояние кластера.

7.​ Распределённый обмен сообщениями.

●​ Spring Batch — платформа для разработки пакетных приложений.


Spring Batch подойдёт как для простых, так и для более сложных
проектов — платформа легко масштабируется и может обрабатывать
большие объёмы информации.

Характеристики

1.​ Управление транзакциями.

2.​ Обработка на основе фрагментов данных.

3.​ Декларативный ввод / вывод.

4.​ Веб-интерфейс администрирования (Spring Cloud Data Flow).

52.​Spring Inversion of Control (IoC) контейнер Spring.

Spring предоставляет IoC-контейнер, который отвечает за управление


жизненным циклом бинов (объектов, управляемых Spring). Базовый
интерфейс для этого контейнера — BeanFactory. Однако в большинстве
приложений используется ApplicationContext, который расширяет
BeanFactory и предлагает дополнительные функции.

Ключевая особенность приложения, написанного на Spring, состоит в том


что большую часть объектов создаем не мы, а Spring. Мы лишь
конфигурируем классы (с помощью аннотаций либо в конфигурационном
XML), чтобы «объяснить» фреймворку Spring, какие именно объекты он
должен создать за нас, и полями каких объектов их сделать. Spring
управляет созданием объектов и потому его контейнер называется
IoC-контейнер. IoC расшифровывается как Inversion of Control. А объекты,
которые создаются контейнером и находятся под его управлением,
называются бинами.

Иллюстрировать это можно так:

В общем на вход контейнер Spring принимает:

●​ Наши обычные классы (которые впоследствии будут бинами).

●​ Конфигурацию (неважно как именно ее задавать – либо в


специальном файле XML, либо с помощью специальных аннотаций).

А на выходе он производит объекты – бины. То есть экземпляры классов,


созданные в соответствии с конфигурацией и внедренные куда нужно (в
другие бины). После этого никакие операторы new нам не понадобятся, мы
будем работать в классе-бине с его полями-бинами так, будто они уже
инициированы. Конечно, не со всеми полями, а только с теми, которые
сконфигурированы как бины. Остальные инициализируются как обычно, в
том числе с помощью оператора new.

53.​Dependency Injection (DI) в Spring.


Dependency Injection (DI) — это паттерн проектирования, который
позволяет объектам получать зависимости извне вместо создания их
самостоятельно. В Spring DI является ключевым механизмом,
обеспечивающим инверсию управления (IoC) в приложении.

Основные принципы DI:​


​ 1) Инверсия управления: вместо создания объектов и управления
их зависимостями вручную, Spring берет эту задачу на себя.​
​ 2) Разделение ответственности: объекты только используют
зависимости, но не создают их, что улучшает тестируемость и
модульность кода.
Реализация DI в Spring
В Spring DI достигается через контейнер IoC, который управляет
созданием, конфигурированием и связыванием объектов. Существует три
способа внедрения зависимостей:

1) Внедрение через конструктор – Рекомендуемый подход для


внедрения обязательных зависимостей.​
Пример:
@Component​
public class Service {​
​ private final Repository repository;​
​ public Service(Repository repository) { // Внедрение зависимости
через конструктор​
​ ​ this.repository = repository;​
​ }​
​ public void doSomething() {​
​ ​ repository.save();​
​ }​
}

@Component​
public class Repository {​
​ public void save() {​
​ ​ System.out.println("Данные сохранены!");​
​ }​
}

Контейнер Spring автоматически создаст объект Repository и передаст его в


Service.

2) Внедрение через сеттер – Используется для внедрения


необязательных зависимостей.​
Пример:
@Component​
public class Service {​
​ private Repository repository;​
​ @Autowired​
​ public void setRepository(Repository repository) { // Внедрение через
сеттер​
​ ​ this.repository = repository;​
​ }​
​ public void doSomething() {​
​ ​ repository.save();​
​ }​
}

3) Внедрение через поле – Наиболее простой, но менее гибкий


способ. Используется с аннотацией @Autowired.​
Пример:
@Component​
public class Service {​
​ @Autowired​
​ private Repository repository;​
​ public void doSomething() {​
​ ​ repository.save();​
​ }​
}

Аннотации для DI в Spring


1) @Component — указывает, что класс является компонентом,
управляемым Spring.​
​ 2) @Autowired — автоматически внедряет зависимости (может
использоваться на конструкторах, сеттерах или полях).​
​ 3) @Qualifier — уточняет, какой именно компонент внедрять, если
их несколько.​
​ 4) @Primary — отмечает предпочтительный компонент, если их
несколько.​
​ 5) @Configuration и @Bean — используются для явного создания
бинов.

Пример с явной конфигурацией:

@Configuration​
public class AppConfig {​
​ @Bean​
​ public Repository repository() {return new Repository();}
@Bean​
​ public Service service(Repository repository) {return new
Service(repository);}

Преимущества Dependency Injection


1) Модульность: уменьшает связанность между классами.​
​ 2) Тестируемость: упрощает создание юнит-тестов, позволяя легко
использовать моки.​
​ 3) Гибкость: позволяет менять зависимости без изменения кода.​
​ 4) Упрощение кода: Spring берет на себя управление
зависимостями.
54.​Жизненный цикл объекта Bean Spring.
Если кратко:
[Создание Bean] -> [Внедрение зависимостей] -> [Пост-обработка до
инициализации] -> [Инициализация] -> [Пост-обработка после
инициализации] -> [Использование Bean] -> [Уничтожение]
Создание Bean​
Контейнер Spring создает экземпляр объекта Bean с помощью рефлексии на
основании конфигурации (Java-код, XML или аннотации). На этом этапе не
выполняется внедрение зависимостей.
Внедрение зависимостей (Dependency Injection)​
Контейнер устанавливает значения свойств и передает зависимости через
конструктор, сеттеры или поле (в случае аннотации @Autowired), а также через
конфигурацию XML.
Пост-обработка Bean (Post-Processing)​
На этом этапе контейнер вызывает метод postProcessBeforeInitialization у всех
зарегистрированных бинов, которые реализуют интерфейс BeanPostProcessor.
Это позволяет выполнять кастомную логику до инициализации Bean.
Инициализация Bean​
После пост-обработки вызывается метод инициализации.
●​ Если Bean реализует интерфейс InitializingBean, вызывается его метод
afterPropertiesSet().

●​ Если задан пользовательский метод инициализации (например, через


аннотацию @Bean(initMethod = "init") или XML-атрибут init-method),
он также будет вызван.

Пост-обработка после инициализации (Post-Initialization)​


Контейнер вызывает метод postProcessAfterInitialization у всех бинов,
реализующих BeanPostProcessor. Это позволяет модифицировать или обернуть
Bean после его инициализации.
Использование Bean​
После всех этапов инициализации Bean готов к использованию. На этом этапе
объект выполняет свои бизнес-функции.
Завершение работы (Destroy)​
Когда контейнер завершает свою работу, он уничтожает Bean:
●​ Если Bean реализует интерфейс DisposableBean, вызывается метод
destroy().
●​ Если задан пользовательский метод уничтожения (через
@Bean(destroyMethod = "cleanup") или XML-атрибут destroy-method),
он также вызывается.
55.​Конфигурация ApplicationContext с помощью xml в Spring.
ApplicationContext — это главный интерфейс в Spring-приложении,
который предоставляет информацию о конфигурации приложения.

Первый этап - чтение конфигураций и создание BeanDefinition.

BeanDefinition — это интерфейс, который описывает бин, его свойства,


аргументы конструктора и другую метаинформацию.

Что касается конфигурации самих бинов, у Spring есть 4 способа


конфигурации. Один из них - Xml конфигурация —
ClassPathXmlApplicationContext(”context.xml”);

XML-конфигурация позволяет определить:

1.​ Бины и их зависимости.


2.​ Указание сканируемых пакетов для автоматической регистрации
бинов.
3.​ Настройку дополнительных модулей, таких как транзакции, AOP и
другие.

Создаем XML-файл (например, applicationContext.xml):

<?xml version="1.0" encoding="UTF-8"?>


<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans.xsd">

<!-- Определение Engine -->


<bean id="engine" class="Engine">
<property name="type" value="V8" />
</bean>

<!-- Определение Car -->


<bean id="car" class="Car">
<property name="engine" ref="engine" />
</bean>
</beans>

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {


public static void main(String[] args) {
ApplicationContext context = new
ClassPathXmlApplicationContext("applicationContext.xml");
Car car = context.getBean("car", Car.class);
car.start();
}
}
XML также может использоваться для активации аннотаций и
автоматического сканирования бинов.

@Component public class Engine { public String getType() { return "V6"; } }

<!-- Сканирование пакета на наличие компонентов -->


<context:component-scan base-package="com.example" />

ApplicationContext context = new


ClassPathXmlApplicationContext("applicationContext.xml"); ​
Car car = context.getBean(Car.class); ​
car.start();

56.​Область видимости Bean в Spring.


Область видимости (scope) определяет, как и сколько раз бин создается и
используется в рамках приложения.

Пример определения области:


класс определения бина:

xml:
Основные области видимости:
●​ Singleton (по умолчанию)
контейнер создаёт один экземпляр этого компонента; все запросы к
этому компоненту будут возвращать один и тот же объект, который
кэшируется. Любые изменения объекта будут отражаться во всех
ссылках на компонент.
Подходит для статичных, неизменяемых объектов, общих для
приложения.
●​ Prototype
Каждый раз, когда бин запрашивается у контейнера, создается новый
экземпляр.Полезно для состояния объектов, которое изменяется при
каждом использовании.
●​ Request
Новый бин создается для каждого HTTP-запроса.
Используется в веб-приложениях для работы с данными конкретного
запроса.
●​ Session
​ Новый бин создается для каждой HTTP-сессии.
Полезно для хранения пользовательских данных, которые должны
сохраняться на протяжении сессии.
●​ Global Session
Создаётся один экземпляр бина на каждую глобальную HTTP сессию.

57.​Фабричные или factory-методы в Spring.


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

Преимущества использования фабричных методов

●​ Инкапсуляция логики создания объектов : определиться с закрытием


деталей создания объектов от клиента.
●​ Гибкость : Легко под угрозой при создании различных объектов.

●​ Расширяемость : Можно изменять способ создания объектов без


изменения клиентского кода.

●​ Поддержка шаблона Singleton : Фабричные методы упрощают контроль


над созданием единственного экземпляра класса.

●​ Поддержка инверсии управления (IoC) : В Spring фабричные методы


интегрируются с контейнером IoC для управления бинарными файлами.

В Spring существует три типа фабричных методов:

●​ Статический фабричный метод для шаблона Singleton

Этот метод используется для возврата единственного экземпляра


собственного класса. Такой подход часто применяется для шаблона
обеспечения Singleton, когда требуется иметь только один экземпляр
класса во всем приложении.

●​ Статический фабричный метод создания экземпляров другого класса

Данный метод используется для создания и возврата экземпляров другого


класса. Он применяется, когда процесс создания объекта требует логики,
обеспечивающей время выполнения программы.

●​ Нестатический фабричный метод

Метод этого типа возникает в экземпляре класса и используется для


возврата данных другого класса. Он позволяет сделать процесс создания
более гибким и подстраиваемым в соответствии с конкретными
требованиями.

58.​Конфигурация ApplicationContext с помощью аннотаций в Spring.

Основные аннотации для конфигурации


ApplicationContext

1.​ @Configuration: Эта аннотация указывает, что класс содержит


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

2.​ @Bean: Эта аннотация используется для определения бина в методе


класса, помеченного @Configuration. Метод, аннотированный @Bean,
должен возвращать объект, который будет управляться контейнером
Spring.

3.​ @Component: Эта аннотация используется для автоматического


обнаружения и регистрации бинов. Классы, помеченные @Component,
будут автоматически сканироваться и добавляться в контекст.

4.​ @Autowired: Эта аннотация используется для автоматического


внедрения зависимостей. Spring будет автоматически разрешать
зависимости и внедрять необходимые бины.

5.​ @ComponentScan: Эта аннотация указывает Spring, где искать


компоненты для автоматического сканирования и регистрации.

6.​ @Value: Эта аннотация используется для внедрения значений из


конфигурационных файлов (например, application.properties).

59.​Связывание в Spring, аннотация @Autowired.


Связывание (Dependency Injection)

Механизм внедрения зависимостей, при котором Spring автоматически создает и


управляет объектами, подставляя их в нужные места.

class Engine {}

class Car { private Engine engine; public Car(Engine engine) { this.engine = engine; } }

Аннотация @Autowired

Автоматически внедряет зависимости в поля, конструкторы или сеттеры. Работает с


контейнером Spring, который управляет зависимостями.

@Component class Engine {}

@Component class Car { @Autowired private Engine engine; }

Способы внедрения зависимостей

1. Через конструктор (предпочтительный).


2. Через поле.

3. Через сеттер.

@Autowired public Car(Engine engine) { this.engine = engine; }

60.​Архитектурный стиль REST.

REST (Representational State Transfer) — это архитектурный стиль проектирования


распределённых систем, особенно веб-сервисов. REST основывается на
использовании стандартов веба (HTTP, URI и т. д.) для взаимодействия между
клиентом и сервером

Принципы REST

Клиент-серверная архитектура: клиент и сервер разделены, взаимодействуют через


API.

Отсутствие состояния (stateless): сервер не хранит информацию о состоянии


клиента между запросами.

Кэшируемость: ответы могут кэшироваться для повышения производительности.

Единообразие интерфейса: работа с ресурсами через URI и методы HTTP.

Слои (layered system): сервер может иметь промежуточные слои (балансировщики,


кэши).

Гипермедиа (HATEOAS): клиент получает ссылки на доступные действия в ответе.

Преимущества REST

●​ Простота и понятность.
●​ Масштабируемость и независимость клиента/сервера.
●​ Поддержка кэширования.

61.​Spring Web-MVC, основная схема и логика работы.

Spring MVC — это веб-фреймворк Spring. Он позволяет создавать


веб-сайты или RESTful сервисы (например, JSON/XML) и хорошо
интегрируется в экосистему Spring, например, он поддерживает
контроллеры и REST контроллеры в ваших Spring Boot приложениях.

Данный подход разделяет приложение на три основных компонента:


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

➢​Модель (Model) отвечает за работу с данными, включая их


хранение, обработку и валидацию;
➢​Контроллер (Controller) реализует логику обработки
HTTP-запросов и использует стандартные методы REST для
выполнения операций над ресурсами;
➢​Представление (View) формирует данные, которые возвращаются
клиенту.

Таким образом, обеспечивается динамическое взаимодействие между


пользователем и сервером, где данные проходят через все основные слои
приложения.

Вся логика работы Spring MVC построена вокруг DispatcherServlet,


который принимает и обрабатывает все HTTP-запросы (из UI) и ответы на
них (последовательность событий, соответствующая входящему
HTTP-запросу):

1.​ После получения HTTP-запроса DispatcherServlet обращается к


интерфейсу HandlerMapping, который определяет, какой
Контроллер должен быть вызван, после чего, отправляет запрос в
нужный Контроллер.

2.​ Контроллер принимает запрос и вызывает соответствующий


служебный метод, основанный на GET или POST. Вызванный метод
определяет данные Модели, основанные на определённой
бизнес-логике и возвращает в DispatcherServlet имя Вида (View).

3.​ При помощи интерфейса ViewResolver DispatcherServlet определяет,


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

4.​ После того, как Вид (View) создан, DispatcherServlet отправляет


данные Модели в виде атрибутов в Вид, который в конечном итоге
отображается в браузере.

62.​Класс DispatcherServlet, его функции.

DispatcherServlet — это центральный компонент в архитектуре Spring


MVC. Он является реализацией паттерна Front Controller и служит точкой
входа для обработки HTTP-запросов в веб-приложении Spring.

Основные функции DispatcherServlet:

1.​ Роутинг запросов:

a.​ Перенаправляет входящие HTTP-запросы к соответствующим


обработчикам (контроллерам).

b.​ Основан на настройках маршрутов, заданных с помощью


аннотаций (@RequestMapping, @GetMapping и т.д.) или
конфигурации XML/Java.

2.​ Координирует работу различных компонентов, таких как


контроллеры, обработчики представлений, резолверы (решатели) и
обработчики исключений.

3.​ Обработка данных запроса и ответа:


a.​ Извлекает данные из запроса (параметры, тело, заголовки) и
передает их в контроллеры.

b.​ Возвращает ответ клиенту в формате, который задается


обработчиком (JSON, XML, HTML и т.д.).

4.​ Использует модель данных, сформированную контроллером, и


передает ее представлению (например, JSP, Thymeleaf, JSON).

5.​ Позволяет обрабатывать исключения централизованно с помощью


механизмов, таких как аннотация @ExceptionHandler или
глобальные обработчики (ControllerAdvice).

6.​ Работает с цепочкой фильтров и интерцепторов (например, для


логирования, авторизации, мониторинга).

Жизненный цикл обработки запроса:

1.​ Клиент отправляет запрос на сервер.

2.​ DispatcherServlet принимает его.

3.​ Запрос передается в цепочку обработчиков через HandlerMapping,


которая сопоставляет путь запроса с контроллером.

4.​ DispatcherServlet вызывает соответствующий метод контроллера.

5.​ Контроллер формирует данные модели и возвращает их вместе с


именем представления.

6.​ С помощью ViewResolver определяется, какое представление будет


использоваться (например, JSP, Thymeleaf).

7.​ Представление рендерится и отправляется клиенту.


63.​Маппинг в Spring.
Маппинг в Spring — это процесс связывания HTTP-запросов (или других
запросов) с методами в контроллерах, а также привязка параметров
запросов к параметрам методов. Spring предоставляет удобные механизмы
маппинга через аннотации, такие как @RequestMapping, @GetMapping,
@PostMapping, @PutMapping, @DeleteMapping, и другие.

Маппинг в Spring играет важную роль в том, как веб-приложение


обрабатывает различные типы запросов от клиента и как эти запросы
направляются к правильным методам контроллеров.

1. Основные аннотации маппинга

1.1. @RequestMapping

Аннотация @RequestMapping является базовой аннотацией для маппинга


HTTP-запросов. Она может быть использована для маппинга как классов,
так и методов, на определенные URL-шаблоны, HTTP-методы, параметры
запросов и другие атрибуты.

Пример использования @RequestMapping:


@Controller

public class MyController {

​ @RequestMapping("/home")

​ public String homePage() {

​ return "home"; // возвращаем представление "home"

​ }

1.2. @GetMapping, @PostMapping, @PutMapping, @DeleteMapping

Для более специализированного маппинга HTTP-методов Spring 4.3 и


выше предоставляет аннотации для конкретных методов HTTP:

●​ @GetMapping — для обработки HTTP GET запросов.

●​ @PostMapping — для обработки HTTP POST запросов.

●​ @PutMapping — для обработки HTTP PUT запросов.

●​ @DeleteMapping — для обработки HTTP DELETE запросов.

Пример использования этих аннотаций:

@Controller

public class UserController {

​ @GetMapping("/users/{id}")

​ public String getUser(@PathVariable("id") Long id, Model model) {

​ User user = userService.getUserById(id);

​ model.addAttribute("user", user);

​ return "userDetails"; // отображение страницы с деталями пользователя

​ }

​ @PostMapping("/users")
​ public String createUser(@ModelAttribute User user) {

​ userService.createUser(user);

​ return "redirect:/users"; // редирект на список пользователей

​ }

​ @PutMapping("/users/{id}")

​ public String updateUser(@PathVariable("id") Long id, @ModelAttribute User


user) {

​ userService.updateUser(id, user);

​ return "redirect:/users/{id}";

​ }

​ @DeleteMapping("/users/{id}")

​ public String deleteUser(@PathVariable("id") Long id) {

​ userService.deleteUser(id);

​ return "redirect:/users";

​ }

1.3. Атрибуты аннотации @RequestMapping

@RequestMappingможет использоваться с несколькими атрибутами, чтобы


более точно настроить маппинг запросов. Вот основные атрибуты:

●​ value — указывает URL-шаблон, с которым будет связано действие.

●​ method — указывает HTTP-метод (GET, POST, PUT, DELETE).

●​ params— маппинг будет выполняться только при наличии


определенных параметров запроса.

●​ — маппинг выполняется только при наличии определенных


headers
HTTP-заголовков.

●​ produces— указывает тип контента, который контроллер может


вернуть (например, application/json).
●​ consumes— указывает тип контента, который метод контроллера
может обработать (например, application/json).

Пример с аттрибутами:

@RequestMapping(value = "/users", method = RequestMethod.POST,


consumes = "application/json", produces = "application/json")

@ResponseBody

public User createUser(@RequestBody User user) {

​ return userService.createUser(user);

В этом примере запросы с методом POST, типом контента application/json


и ожидаемым типом ответа application/json будут обработаны этим
методом.

2. Маппинг с использованием параметров

Маппинг параметров — это механизм связывания данных из URL,


формы или тела запроса с параметрами метода контроллера. Spring
поддерживает несколько способов маппинга параметров:

2.1. Маппинг параметров URL с использованием @PathVariable

@PathVariable используется для извлечения значений из URI.

Пример:

@GetMapping("/users/{id}")

public String getUser(@PathVariable("id") Long id) {

​ return "User ID: " + id;

2.2. Маппинг параметров запроса с использованием @RequestParam

@RequestParam используется для извлечения параметров запроса из строки


запроса URL.
Пример:

@GetMapping("/search")

public String search(@RequestParam("query") String query) {

​ return "Searching for: " + query;

Для работы с параметрами, которые могут быть необязательными, можно


использовать атрибут defaultValue:

@GetMapping("/search")

public String search(@RequestParam(value = "query", defaultValue = "default")


String query) {

​ return "Searching for: " + query;

2.3. Маппинг данных из тела запроса с использованием @RequestBody

@RequestBody используется для извлечения данных из тела запроса,


например, в формате JSON или XML, и преобразования их в Java-объект.

Пример:

@PostMapping("/users")

public String createUser(@RequestBody User user) {

​ userService.createUser(user);

​ return "User created";

2.4. Маппинг данных формы с использованием @ModelAttribute

@ModelAttributeиспользуется для связывания данных из формы (или


другого источника) с объектом Java.

Пример:
@PostMapping("/users")

public String createUser(@ModelAttribute User user) {

​ userService.createUser(user);

​ return "redirect:/users";

3. Маппинг и возвращаемые значения

Методы контроллеров в Spring могут возвращать несколько типов


значений, таких как строки, объекты, представления, JSON, и т.д. Spring
автоматически обрабатывает эти типы в зависимости от контекста:

●​ Строка — возвращаемое значение интерпретируется как имя


представления.

●​ Объекты — если метод возвращает объект, и тип ответа настроен


как JSON или XML, Spring будет автоматически преобразовывать
объект в соответствующий формат.

●​ @ResponseBody— аннотация, которая указывает, что метод


контроллера должен возвращать тело ответа (например, JSON или
XML).

Пример:

@GetMapping("/users/{id}")

@ResponseBody

public User getUser(@PathVariable Long id) {

​ return userService.getUser(id); // Spring автоматически преобразует


объект User в JSON

}
64.​Интерфейсы HttpServletRequest и HttpServletResponse.

Основная информация
HttpServletRequest HttpServletResponse

Получает информацию о запросе клиента. Формирует ответ клиенту.

Позволяет работать с параметрами, URI, Позволяет задавать статус, заголовки,


заголовками, cookies. cookies и тело ответа.

Используется для обработки данных, Используется для отправки данных


отправленных клиентом. клиенту.

Интерфейс HttpServletRequest используется для получения информации о


клиентском запросе. Он наследует интерфейс ServletRequest и
предоставляет методы для обработки данных запроса.​
Основные методы:

1) Получение параметров и атрибутов:

○​ String getParameter(String name) — возвращает значение


параметра.
○​ String[] getParameterValues(String name) — возвращает все
значения параметра.

2) Информация о запросе:

○​ String getMethod() — возвращает метод HTTP-запроса (GET,


POST и т. д.).
○​ String getQueryString() — возвращает строку параметров
запроса.
○​ String getRemoteAddr() — возвращает IP-адрес и имя клиента.

3) Работа с cookies:

○​ Cookie[] getCookies() — возвращает массив cookies,


переданных с запросом.

Пример использования: String param = request.getParameter("username");


Интерфейс HttpServletResponse используется для формирования
HTTP-ответа, отправляемого клиенту. Он наследует интерфейс
ServletResponse.

Основные методы:

1) Формирование тела ответа:

○​ ServletOutputStream getOutputStream() — поток для записи


бинарных данных.
○​ PrintWriter getWriter() — поток для записи текстовых данных.

2) Управление заголовками и статусом:

○​ void setHeader(String name, String value) — добавляет или


изменяет заголовок.
○​ void setDateHeader(String name, long date) — добавляет дату в
заголовок.
○​ void sendError(int sc, String msg) — отправляет HTTP-ошибку.

3) Работа с cookies:

○​ void addCookie(Cookie c) — добавляет cookie в ответ.

4) Перенаправление:

○​ void sendRedirect(String location) — перенаправляет запрос на


указанный URL.

65.​Архитектурный стиль CRUD, его соответствие REST и HTTP.


Архитектурный стиль CRUD (Create, Read, Update, Delete) является
фундаментальным подходом к управлению данными, который часто
ассоциируется с операциями над сущностями в базе данных.​

REST (Representational State Transfer) — это архитектурный стиль для
проектирования распределенных систем, таких как веб-сервисы. CRUD является
важной составляющей REST, поскольку операции CRUD используются для
взаимодействия с ресурсами.​

Связь между CRUD и REST выражается в том, что операции CRUD находят
отражение в действиях REST через HTTP-методы:​


REST строится поверх HTTP, но не ограничивается им. HTTP предоставляет
стандартные методы (например, GET, POST, PUT, DELETE), которые REST
использует для реализации взаимодействия с ресурсами. Ключевые принципы
REST, реализуемые через HTTP:
●​ Идентификация ресурсов через URI.
●​ Статусы ответов HTTP, которые указывают на результат операции.
●​ Без состояния (Stateless). Каждый запрос содержит всю необходимую
информацию для выполнения операции, сервер не хранит информацию о
предыдущих запросах.
●​ Управляемость через гипермедиа (HATEOAS). Сервер может
возвращать гиперссылки, чтобы клиент знал, какие действия можно
выполнить с ресурсом.

66.​Шаблон Data Access Object (DAO).


Шаблон проектирования DAO (Data Access Object) — это способ
организации кода для управления взаимодействием между вашей
программой и базой данных.

Основная идея заключается в том, что создаётся интерфейс (или


абстрактный класс), который описывает все возможные операции с
данными. Это может быть операции добавления, удаления, обновления и
извлечения данных. Затем для каждого конкретного источника данных
создается своя реализация этого интерфейса, в которой эти операции
выполняются конкретным для этого источника данных способом.
Класс User — это просто контейнер для пользовательских данных,
поэтому он не реализует никаких других функций

Интерфейс Dao определяет абстрактный API, который выполняет


операции CRUD над объектами типа T. Благодаря высокому уровню
абстракции, который обеспечивает интерфейс, легко создать конкретную,
детализированную реализацию, работающую с объектами User.

Класс UserDao

Давайте определим пользовательскую реализацию интерфейса Dao:


(фрагмент)

Класс UserDao реализует все функции, необходимые для получения,


обновления и удаления объектов User.

Хотя классы User и UserDao сосуществуют независимо друг от друга в


рамках одного приложения, нам всё равно нужно понять, как можно
использовать последний для сокрытия уровня сохранения данных от
логики приложения:

В этом случае метод main просто использует экземпляр UserDao для


выполнения операций CRUD с несколькими объектами User.

Наиболее важным аспектом этого процесса является то, что UserDao


скрывает от приложения все низкоуровневые детали сохранения,
обновления и удаления объектов.
67.​Основные понятия Объектно-реляционного отображения (ORM -
Object-Relational Mapping).
Объектно-реляционное отображение (ORM) — это техника
программирования, которая позволяет взаимодействовать с базами данных
через объекты и классы языка программирования вместо использования
SQL-запросов. ORM упрощает работу с базами данных, минимизирует ручное
написание SQL-кода и позволяет разработчикам сосредоточиться на логике
приложения.

68.​Спецификация Java Persistence API (JPA).


Java Persistence API (JPA) — это спецификация Java API, которая заполняет
пробел между реляционными базами данных и объектно-ориентированным
программированием, обрабатывая объекты Java в таблицах баз данных и
обратно. Этот процесс известен как объектно-реляционное сопоставление
(ORM) . JPA может определить способ отображения классов Java (сущностей) в
таблицах баз данных и то, как они могут взаимодействовать с базовыми
данными через EntityManager, постоянство контекста и передачу данных.

JPA состоит из трех основных пунктов:

●​ API - интерфейсы в пакете javax.persistance. Набор интерфейсов, которые


позволяют организовать взаимодействие с ORM провайдером.

●​ JPQL - объектный язык запросов. Очень похож на SQL, но запросы


выполняются к объектам.

●​ Metadata - аннотации над объектами. Набор аннотаций, которыми мы


описываем метаданные отображения. Тогда уже JPA знает какой объект в
какую таблицу нужно сохранить. Метаданные можно описывать двумя
способами: XML-файлом или через аннотации.

Ключевые термины в JPA

●​ Сущность (Entity) : Лёгкий объект, представляющий символ в таблице


базы данных. Например, класс Userможет соответствовать таблице users.

●​ EntityManager : Основной интерфейс для работы с сущностями. Он


отвечает за управление их жизненным циклом, синхронизацию данных с
базой и выполнение запросов.
●​ Сохранение контекста (Persistence Context) : Это набор отслеживаемых
объектов EntityManager. Контекст синхронизирует состояние объектов с
базой данных, выявляя их согласованность. Например, изменения в
объектах автоматически применяются к базе в конце передачи.

Сама по себе JPA является спецификацией и не содержит особенностей


реализации. Одной из самых популярных реализаций является Hibernate,
которая предоставляет дополнительные возможности, не описанные в JPA, но
при этом полностью соответствующие критериям.

Используя JPA, разработчики могут создавать, читать, обновлять и удалять


объекты в базе данных, не прибегая к написанию сложных SQL-запросов, что
способствует повышению производительности и упрощению разработки
Java-приложений.

69.​Архитектура ORM Java Persistence API (JPA).


Java Persistence API (JPA) — это спецификация для управления реляционными
данными в Java-приложениях с использованием объектно-ориентированного
подхода. JPA предоставляет стандартный способ работы с базами данных,
позволяя разработчикам использовать объекты Java для взаимодействия с
реляционными данными. Основная цель JPA — упростить работу с базами
данных, скрывая детали SQL и предоставляя более высокоуровневый API для
работы с данными.

Архитектура JPA

Архитектура JPA состоит из нескольких ключевых компонентов, которые


взаимодействуют друг с другом для управления персистентностью объектов.
Основные компоненты архитектуры JPA включают:

-Entity:

Это класс, который представляет собой таблицу в базе данных. Каждый


экземпляр класса Entity соответствует строке в таблице.
Классы Entity аннотируются с помощью аннотаций JPA, таких как @Entity,
@Table, @Id, и других, чтобы указать, как они должны быть сопоставлены с

таблицами базы данных.

-EntityManager:

Это основной интерфейс для взаимодействия с контекстом персистентности.


Он управляет жизненным циклом объектов Entity, выполняет операции CRUD
(создание, чтение, обновление, удаление) и управляет транзакциями.

EntityManager предоставляет методы для поиска, сохранения и удаления

объектов.

-EntityManagerFactory:

Это интерфейс, который создает экземпляры EntityManager. Он управляет


настройками подключения к базе данных и конфигурацией JPA.

Обычно EntityManagerFactory создается один раз за время жизни приложения,


а EntityManager создается по мере необходимости.

-Persistence Context:

Это среда, в которой управляются объекты Entity. Она отслеживает изменения


объектов и синхронизирует их с базой данных.

Все изменения, сделанные в объектах Entity, будут автоматически


отслеживаться и синхронизироваться с базой данных при завершении
транзакции.

-Query Language (JPQL):

JPA предоставляет собственный язык запросов, называемый Java Persistence


Query Language (JPQL), который позволяет выполнять запросы к объектам
Entity, а не к таблицам базы данных.

JPQL основан на SQL, но работает с объектами и их свойствами.


-Transaction Management:

JPA поддерживает управление транзакциями, что позволяет выполнять


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

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


такими как JTA (Java Transaction API) или JDBC.

70.​Основные аннотации Java Persistence API (JPA).


Основные аннотации Java Persistence API (JPA)

Java Persistence API (JPA) — это спецификация для работы с объектно-реляционным


отображением (ORM) в Java, позволяющая взаимодействовать с базами данных через
объектную модель. JPA предоставляет удобный способ управления данными в СУБД
без необходимости написания сложного SQL-кода.

Аннотации JPA используются для определения структуры и поведения сущностей в


базе данных.

Основные аннотации JPA позволяют:

●​ Определять сущности и маппинг на таблицы (@Entity, @Table).

●​ Работать с первичными ключами (@Id, @GeneratedValue).

●​ Определять свойства полей (@Column, @Enumerated, @Temporal).

●​ Определять связи между сущностями (@OneToOne, @OneToMany,


@ManyToOne, @ManyToMany).

●​ Работать с вложенными объектами (@Embeddable, @Embedded).

1. Аннотация @Entity

Обозначает класс как JPA-сущность (таблицу в базе данных). Класс, помеченный этой
аннотацией, должен иметь конструктор без аргументов, а его поля должны быть
связаны с колонками таблицы.

2. Аннотация @Table

Позволяет задать имя таблицы и схему в базе данных для сущности.

Если аннотация @Table не указана, то по умолчанию имя таблицы соответствует


имени класса.
3. Аннотация @Id

Определяет первичный ключ (Primary Key) сущности. Поле, помеченное @Id, должно
быть уникальным и непустым.

4. Аннотация @GeneratedValue

Используется вместе с @Id для автоматической генерации значений первичного


ключа.

Стратегии генерации ключей:

●​ GenerationType.AUTO – стратегия по умолчанию, выбор зависит от


используемой СУБД.

●​ GenerationType.IDENTITY – использует автоинкремент (например,


AUTO_INCREMENT в MySQL).

●​ GenerationType.SEQUENCE – использует последовательность (работает с БД,


поддерживающими SEQUENCE).

●​ GenerationType.TABLE – использует таблицу для хранения идентификаторов.

Пример:

import jakarta.persistence.GeneratedValue;

import jakarta.persistence.GenerationType;

@Entity

public class User {

@Id

@GeneratedValue(strategy = GenerationType.IDENTITY)

private Long id;

5. Аннотация @Column

Определяет параметры колонки в таблице.

Атрибуты:

●​ name — имя колонки.

●​ nullable — допускается ли NULL (по умолчанию true).

●​ length — максимальная длина строки (по умолчанию 255).


●​ unique — должно ли значение быть уникальным.

6. Аннотация @Transient

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


таблице.

Пример:

import jakarta.persistence.Transient;

@Entity

public class User {

private String username;

@Transient

private String tempData; // Не будет сохраняться в БД

7. Аннотация @Enumerated

Используется для хранения enum-типов в базе данных.

Режимы:

●​ EnumType.STRING – сохраняет строковое представление.

●​ EnumType.ORDINAL – сохраняет числовой индекс (по умолчанию).

Пример:

import jakarta.persistence.Enumerated;

import jakarta.persistence.EnumType;

@Entity

public class User {

public enum Status { ACTIVE, INACTIVE }

@Enumerated(EnumType.STRING)

private Status status;

}
8. Аннотация @Temporal (для дат)

Используется для работы с полями типа Date и Calendar, задавая формат хранения в
базе данных.

Режимы:

●​ TemporalType.DATE – только дата (год, месяц, день).

●​ TemporalType.TIME – только время (часы, минуты, секунды).

●​ TemporalType.TIMESTAMP – дата и время.

Пример:

import jakarta.persistence.Temporal;

import jakarta.persistence.TemporalType;

import java.util.Date;

@Entity

public class Event {

@Temporal(TemporalType.TIMESTAMP)

private Date eventDate;

9. Аннотации связей между сущностями

@OneToOne (Связь "один-к-одному") и тд, остальные выше написаны

10. Аннотация @JoinColumn

Используется для задания имени колонки, хранящей внешний ключ в связях между
сущностями.

Пример:

import jakarta.persistence.JoinColumn;

import jakarta.persistence.OneToOne;

@Entity

public class User {


@OneToOne

@JoinColumn(name = "address_id")

private Address address;

11. Аннотация @MappedSuperclass

Позволяет создать класс с полями, которые будут унаследованы другими сущностями,


но сам класс не становится сущностью.

Пример:

import jakarta.persistence.MappedSuperclass;

@MappedSuperclass

public class BaseEntity {

@Id

@GeneratedValue(strategy = GenerationType.IDENTITY)

private Long id;

12. Аннотация @Embeddable и @Embedded

Используется для встраивания объектов в сущности (композиция).

71.​Библиотека Hibernate, основные аннотации.

Библиотека Hibernate и её основные аннотации

Hibernate — это библиотека Java для работы с базами данных, реализующая


концепцию ORM (Object-Relational Mapping). Она позволяет преобразовывать объекты
Java в таблицы базы данных и наоборот, скрывая сложность работы с SQL.

Основные аннотации Hibernate


1. Аннотации для классов

1.​ @Entity
○​ Помечает класс как сущность, связанную с таблицей в базе данных.
○​ Класс должен иметь уникальный идентификатор (@Id).


@Entity
public class User {
@Id
private Long id;
private String name;
}

2.​
3.​ @Table
○​ Указывает таблицу, с которой будет связана сущность.
○​ Необязательна, если имя таблицы совпадает с именем класса.


@Entity
@Table(name = "users")
public class User {
@Id
private Long id;
}

4.​

2. Аннотации для полей

1.​ @Id
○​ Определяет первичный ключ сущности.

@Id
private Long id;

2.​
3.​ @GeneratedValue
○​ Автоматическая генерация значения первичного ключа.
○​ Стратегии:
■​ GenerationType.AUTO: стратегия выбирается Hibernate
автоматически.
■​ GenerationType.IDENTITY: автогенерация на уровне базы
данных.
■​ GenerationType.SEQUENCE: использует последовательности
(sequence) базы данных.
■​ GenerationType.TABLE: хранение ключей в отдельной таблице.

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

4.​
5.​ @Column
○​ Настройка столбца в таблице.
○​ Атрибуты:
■​ name: имя столбца.
■​ nullable: допускает ли значение NULL.
■​ length: длина строки.


@Column(name = "user_name", nullable = false, length = 50)
private String name;

6.​
7.​ @Transient
○​ Указывает, что поле не должно сохраняться в базу данных.​
@Transient

private String tempData;

8.​
9.​ @Lob
○​ Используется для хранения больших объектов, например, текста (CLOB)
или файлов (BLOB).


@Lob
private String description;

10.​
11.​@Enumerated
○​ Для хранения перечислений (enum).
○​ Типы:
■​ EnumType.STRING: сохраняет строковые значения.
■​ EnumType.ORDINAL: сохраняет порядковые номера.

@Enumerated(EnumType.STRING)
private Status status;

12.​

3. Аннотации для связей между сущностями

1.​ @OneToOne
○​ Связь "один к одному".
○​ Используется атрибут mappedBy для двусторонней связи.


@OneToOne
@JoinColumn(name = "profile_id")
private Profile profile;

2.​
3.​ @OneToMany
○​ Связь "один ко многим".
○​ Используется с коллекциями.


@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
private List<Post> posts;

4.​
5.​ @ManyToOne
○​ Связь "многие к одному".


@ManyToOne
@JoinColumn(name = "user_id")
private User user;

6.​
7.​ @ManyToMany
○​ Связь "многие ко многим".
○​ Создаётся промежуточная таблица.

@JoinTable(
name = "user_roles",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "role_id")
)
private Set<Role> roles;

8.​

4. Аннотации для жизненного цикла сущности

1.​ @PrePersist
○​ Метод вызывается перед сохранением новой сущности.

java​
КопироватьРедактировать​
@PrePersist
public void onPrePersist() {
createdAt = LocalDateTime.now();
}

2.​
3.​ @PostPersist
○​ Метод вызывается после сохранения новой сущности.
4.​ @PreUpdate
○​ Вызывается перед обновлением сущности.
5.​ @PostUpdate
○​ Вызывается после обновления сущности.
6.​ @PreRemove
○​ Вызывается перед удалением сущности.
7.​ @PostRemove
○​ Вызывается после удаления сущности.

Пример сущности с аннотациями

import jakarta.persistence.*;
import java.time.LocalDateTime;
import java.util.List;

@Entity
@Table(name = "users")
public class User {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(name = "username", nullable = false, length = 50)


private String name;

@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)


private List<Post> posts;

@PrePersist
public void onPrePersist() {
createdAt = LocalDateTime.now();
}

private LocalDateTime createdAt;

// Геттеры и сеттеры
}

Основные преимущества Hibernate

Автоматизация работы с базой данных: Не нужно писать сложные SQL-запросы


вручную.

Поддержка кэширования: Ускорение доступа к данным.

Портативность: Работает с разными базами данных без изменений в коде.

Легкость работы с ассоциациями: Упрощает работу с отношениями между


сущностями.

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

72.​Объявление сущности и таблицы в Hibernate.

В Hibernate для работы с базой данных сущности представляются в виде


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

Основные аннотации для объявления сущности и таблицы


1.​ @Entity - обозначает класс как сущность Hibernate, которая будет
связана с таблицей в базе данных (Hibernate ожидает, что класс с
этой аннотацией будет иметь аннотацию @Id).
2.​ @Table - опционально используется для указания имени таблицы,
если оно отличается от имени класса.
3.​ @Id - Обозначает первичный ключ.
4.​ @GeneratedValue - указывает стратегию генерации значения для
первичного ключа

●​ GenerationType.IDENTITY: Автоинкремент.
●​ GenerationType.SEQUENCE: Использует последовательности
(например, в PostgreSQL).
●​ GenerationType.TABLE: Хранит значения в специальной
таблице.
●​ GenerationType.AUTO: Автоматический выбор стратегии на
основе базы данных.

5.​ @Column - Позволяет задать параметры для столбцов таблицы,


такие как имя, длина, уникальность и т.д.

●​ name: Имя столбца в таблице.


●​ nullable: Разрешает или запрещает NULL (по умолчанию
true).
●​ unique: Указывает, что значения в столбце должны быть
уникальными.
●​ length: Максимальная длина строки (для строковых полей).

Hibernate поддерживает различные типы связей между сущностями:


➢​@OneToOne (Одна запись в таблице A связана с одной записью в
таблице B):

@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "name")
private String name;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "profile_id", referencedColumnName = "id") // Связь с Profile
private Profile profile;
// Геттеры и сеттеры
}
@Entity
@Table(name = "profiles")
class Profile {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "bio")
private String bio;
// Геттеры и сеттеры
}

➔​ @OneToOne: Указывает связь “один к одному”.


➔​ @JoinColumn: Указывает имя внешнего ключа в таблице users, который ссылается на id
таблицы profiles.

➢​ @OneToMany (Одна запись в таблице A связана с несколькими


записями в таблице B)

@Entity
@Table(name = "categories")
public class Category {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "name")
private String name;
@OneToMany(mappedBy = "category", cascade = CascadeType.ALL, orphanRemoval =
true)
private List<Product> products;
// Геттеры и сеттеры
}
@Entity
@Table(name = "products")
class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "name")
private String name;
@ManyToOne
@JoinColumn(name = "category_id", nullable = false)
private Category category;
// Геттеры и сеттеры
}
➔​ @OneToMany: Указывает, что одна категория связана с несколькими продуктами.
➔​ mappedBy: Указывает поле в классе Product, которое отвечает за связь.
➔​ @ManyToOne: Указывает обратную связь из продукта к категории.

➢​@ManyToOne (Несколько записей в таблице A могут ссылаться на


одну запись в таблице B)

@Entity
@Table(name = "employees")
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "name")
private String name;
@ManyToOne
@JoinColumn(name = "department_id", nullable = false)
private Department department;
// Геттеры и сеттеры
}
@Entity
@Table(name = "departments")
class Department {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "name")
private String name;
@OneToMany(mappedBy = "department", cascade = CascadeType.ALL)
private List<Employee> employees;
// Геттеры и сеттеры
}

➔​ @ManyToOne: Указывает связь из сотрудника в департамент.


➔​ @OneToMany: Указывает обратную связь из департамента к сотрудникам.

➢​@ManyToMany (Несколько записей из таблицы A могут быть


связаны с несколькими записями из таблицы B).

@Entity
@Table(name = "students")
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "name")
private String name;
@ManyToMany
@JoinTable(
name = "student_course",
joinColumns = @JoinColumn(name = "student_id"),
inverseJoinColumns = @JoinColumn(name = "course_id")
)
private Set<Course> courses;
// Геттеры и сеттеры
}
@Entity
@Table(name = "courses")
class Course {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "title")
private String title;
@ManyToMany(mappedBy = "courses")
private Set<Student> students;
// Геттеры и сеттеры
}

➔​ @ManyToMany: Указывает связь “многие ко многим”.


➔​ @JoinTable: Определяет промежуточную таблицу student_course, которая связывает студентов и
курсы.
◆​ joinColumns: Указывает внешний ключ для таблицы students.
◆​ inverseJoinColumns: Указывает внешний ключ для таблицы courses.

73.​Интерфейс Session в Hibernate.

Интерфейс Session в Hibernate является ключевым компонентом


ORM-фреймворка Hibernate. Он предоставляет API для взаимодействия с
базой данных. Session управляет жизненным циклом объектов, выполняет
CRUD-операции, и позволяет выполнять запросы к базе данных.

●​ Session отвечает за создание транзакции и взаимодействие с базой


данных.

●​ Использует соединение JDBC под капотом для выполнения запросов.

●​ Обеспечивает поддержку операций CRUD:

○​ save(), persist(), update(), merge(), delete().


●​ Сопоставляет объекты Java с таблицами в базе данных согласно
настройкам в ORM-модели.

●​ Использует первичный кэш (First Level Cache), что означает, что все
изменения объектов отслеживаются в пределах одного сеанса.

●​ Кэш на уровне сеанса позволяет минимизировать количество


обращений к базе данных.

●​ Поддерживает выполнение HQL (Hibernate Query Language), SQL, а


также Criteria API.

●​ Session позволяет создавать объекты Transaction и явно управлять


ими.

○​ Transaction transaction = session.beginTransaction();

●​ Объект Session не является потокобезопасным и должен


использоваться в пределах одного потока.

●​ После завершения работы с Session, её нужно закрыть через


session.close().

●​ Автоматически сохраняет изменения объектов в базе данных при


закрытии сессии или выполнении транзакции.

Сессия управляет состояниями объектов:

●​ Transient: объект не связан с базой данных.

●​ Persistent: объект управляется Hibernate и синхронизируется с базой


данных.

●​ Detached: объект больше не управляется Hibernate.

Session — это интерфейс, представляющий собой обертку над


соединением с базой данных. Он обеспечивает прозрачную работу с
объектами, их синхронизацию с базой данных и эффективное управление
кэшированием.
74.​Ассоциация сущностей в Hibernate.

Hibernate — это инструмент ORM (Object-Relational Mapping), который


облегчает работу Java-разработчиков с базами данных.

Связи между сущностями (Associations): Hibernate поддерживает


различные типы ассоциаций (один-к-одному, один-ко-многим,
многие-ко-многим) - это упрощает управления связанными объектами.

Для определения связей между сущностями Hibernate использует


аннотации @OneToOne, @OneToMany, @ManyToOne, @ManyToMany.

@OneToOne

Каждый гражданин может иметь только один паспорт. И у каждого


паспорта может быть только один владелец. Такая связь двух объектов в
Hibernate определяется как @OneToOne (один-к-одному).

просто для справки:


Параметр optional говорит JPA, является ли значение в этом поле
обязательным или нет. Связанное поле в User объявлено с помощью
аннотации @JoinColumn, параметр name которой обозначает поле в БД для
создания связи. Для того, чтобы объявить сторону, которая не несет
ответственности за отношения, используется атрибут mappedBy в
сущности Passport. Он ссылается на имя свойства связи (passport) на
стороне владельца.

Со стороны владельца к аннотации @OneToOne добавляется параметр


cascade. В однонаправленных отношениях одна из сторон (и только одна)
должна быть владельцем и нести ответственность за обновление
связанных полей. В этом случае владельцем выступает сущность User.
Каскадирование позволяет указать JPA, что необходимо «сделать со
связанным объектом при выполнении операции с владельцем». То есть,
когда удаляется Person из базы, JPA самостоятельно определит наличие у него
паспорта и удалит сначала паспорт, потом гражданина.

@OneToMany и @ManyToOne

Аннотации @OneToMany (один-ко-многим) и @ManyToOne


(многие-к-одному) рассмотрим на примере гражданина и его места
проживания.
Поскольку по одному адресу может проживать несколько жильцов, то поле
tenants представлено коллекцией, которая имеет аннотацию @OneToMany.
Параметр mappedBy также указывает на поле в классе владельца.
Параметр fetch=FetchType.EAGER говорит о том, что при загрузке
владеемого объекта необходимо сразу загрузить и коллекцию владельцев.

Для чтения связанных объектов из БД используются следующие стратегии


загрузок (fetch) : EAGER и LAZY. В первом случае объекты коллекции
сразу загружаются в память, во втором случае — только при обращении к
ним.

@ManyToMany

Примером ассоциации @ManyToMany (многие-ко-многим) могут быть


отношения студентов и ВУЗов. В одном институте может быть много
студентов, студент может учиться в нескольких ВУЗах.

Для определения связи @ManyToMany в примере потребуется три


таблицы : таблица студентов students, таблица ВУЗов university и таблица
связей student_university, в которой будут связаны студенты и ВУЗы. Кроме
этого в таблице student_university определены внешние ключи (FOREIGN
KEY), предупреждающие появление непрошенных записей при отсутствии
родительских.

Список институтов в сущности Student аннотирован с помощью


@ManyToMany. Далее следует аннотация @JoinTable, которая определяет
таблицу и поля для связи. Параметр name указывает название таблицы
(student_university). Параметр joinColumns указывает на поле, которое
используется для прямой связи (идентификатор student_id). Параметр
inverseJoinColumns указывает на поле, которое используется для обратной
связи (идентификатор university_id). Для указания столбцов связи из
таблицы используется аннотация @JoinColumn.
Также существуют двунаправленные и однонаправленные ассоциации:

-​ Двунаправленная ассоциация в Hibernate — это связь между


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

-​ Однонаправленная ассоциация возникает, когда только одна из


двух сущностей содержит ссылку на другую.

75.​Spring Boot: определение, характеристики, преимущества.

Spring Boot — это инструмент на базе фреймворка Spring,


предназначенный для упрощения разработки, настройки и развертывания
приложений. Основная цель Spring Boot — минимизировать сложность
конфигурации и ускорить процесс создания приложений за счет
автоматизации и предустановленных настроек.

Характеристики Spring Boot

1) Автоконфигурация (Auto-Configuration):​
Автоматически настраивает компоненты приложения на основе
зависимостей в проекте. Например, если в зависимости добавлена база
данных, Spring Boot автоматически подключает JDBC и настраивает
соединение.​
​ 2) Встроенные серверы (Embedded Servers):​
Включает встроенные серверы, такие как Tomcat, Jetty, Undertow, что
позволяет запускать приложение как автономный Java-приложение без
необходимости установки внешнего сервера.​
​ 3) Spring Initializer:​
Предоставляет веб-инструмент для быстрого создания проекта с
предустановленными зависимостями.​
​ 4) Упрощенная настройка:​
Использование файла конфигурации application.properties или
application.yml вместо обширных XML-конфигураций.​
​ 5) Поддержка микросервисов:​
Spring Boot идеально подходит для создания микросервисной
архитектуры благодаря своей легковесности и совместимости с
инструментами, такими как Spring Cloud.​
​ 6) Модульное подключение зависимостей:​
Spring Boot Starter-пакеты предоставляют готовые зависимости для
разных функций, например:​
​ ​ spring-boot-starter-web — для веб-приложений.​
​ ​ spring-boot-starter-data-jpa — для работы с базами данных.

Преимущества:

1) Быстрое развертывание:​
Благодаря автоконфигурации и встроенным серверам, приложение можно
запустить с минимальными настройками.

2) Минимум кода и конфигурации:​


Нет необходимости писать много шаблонного кода или конфигураций
XML. Всё настраивается с помощью аннотаций и файлов свойств.

3) Легкость тестирования:​
Поддерживает встроенные инструменты для модульного и
интеграционного тестирования.

4) Совместимость с экосистемой Spring:​


Полностью интегрируется с библиотеками Spring, такими как Spring
Security, Spring Data, Spring Cloud и др.

5) Гибкость:​
Позволяет переопределять настройки автоконфигурации, если это
необходимо.​
76.​Spring Initializr, особенности и преимущества применения.
Spring Initializr — это веб-сервис и инструмент для быстрого создания проекта
на основе фреймворка Spring. Он позволяет легко генерировать готовый шаблон
проекта с необходимыми зависимостями, минимальной конфигурацией и
структурой. ​

Сервис доступен через веб-интерфейс https://start.spring.io, а также интегрирован
в популярные IDE, такие как IntelliJ IDEA, Eclipse, и Visual Studio Code.​

Особенности Spring Initializr
●​ Поддержка различных зависимостей (например, Spring Web, Spring Data
JPA, Spring Security)
●​ Выбор языка и версий: Поддержка Java, Kotlin и Groovy. Возможность
выбора версии Spring Boot
●​ Различные системы сборки (Maven и Gradle)
●​ Интеграция с IDE
●​ Поддержка микросервисной архитектуры
Преимущества применения Spring Initializr
●​ Экономия времени: Вместо ручной настройки проекта, зависимости и
структуры, Spring Initializr автоматически генерирует рабочий проект, что
сокращает время начала разработки.
●​ Минимизация ошибок: Генератор автоматически добавляет
необходимые зависимости и конфигурации, что снижает вероятность
ошибок.
●​ Гибкость и кастомизация: Пользователь может настроить проект под
свои потребности, выбирая только нужные библиотеки и версии.
●​ Обеспечение совместимости: Initializr подбирает правильные версии
зависимостей, которые совместимы с выбранной версией Spring Boot, что
экономит время на проверку совместимости.
●​ Удобство для новичков: Простота выбора и минимальная необходимость
знаний о внутренних зависимостях Spring делают Initializr отличным
стартовым инструментом для начинающих.
77.​Структура фреймворка JUnit.
JUnit — фреймворк для автоматического юнит-тестирования приложений.
Он содержит специальные функции и правила, которые позволяют легко
писать и запускать тесты, то есть проверять, что каждый блок кода, или
модуль, ответственный за определенную функцию программы, работает
как надо. Такой вид тестирования называют модульным, или
юнит-тестированием.
Аннотации в JUnit — это специальные метки, которые Java-разработчик
размещает перед методами в тестовом классе. Они позволяют настраивать
процесс тестирования, указывая фреймворку, как именно их следует
обрабатывать. Например, можно явно указать, какие из методов являются
тестовыми случаями, какие из них выполнять перед тестами и после и так
далее.
Вот несколько базовых аннотаций.
●​ @Test. Эту аннотацию ставим перед методами, которые относятся к
тестовым случаям. JUnit поймёт, что их следует выполнять в
качестве теста, а по завершении проверить результат.
●​ @Before. Используется для методов, которые должны быть
выполнены перед каждым тестовым случаем. Например, если у нас
есть несколько тестов, которые требуют одних и тех же начальных
условий, мы можем обозначить метод с аннотацией @Before, задав
необходимые условия тестирования один раз.
●​ @After. Эту аннотацию используем перед методом, который должен
быть выполнен после тестового случая.
●​ @BeforeClass, @AfterClass. Методы с аннотацией @BeforeClass
выполняются перед запуском первого теста в классе, а методы с
аннотацией @AfterClass — после завершения всех тестов в классе.
●​ @Ignore. Используется перед методом, чтобы отключить его
выполнение в тесте. Это может быть полезно, если мы не уверены в
работоспособности отдельных тестов и не хотим их использовать, но
должны оставить в коде.
public class MyTest {
@BeforeEach
public void setUp() {
// Метод, выполняющийся перед каждым тестовым
случаем
}
@AfterEach
public void tearDown() {
// Метод, выполняющийся после каждого тестового
случая
}
Assertions - методы для проверки условий (результатов теста):
●​ assertEquals(expected, actual) — проверяет равенство.
●​ assertNotEquals(expected, actual) — проверяет, что значения не равны.
●​ assertTrue(condition) — проверяет, что условие истинно.
●​ assertFalse(condition) — проверяет, что условие ложно.
●​ assertThrows(Exception.class, executable) — проверяет, что
выбрасывается исключение.
●​ assertNull(object) — проверяет, что объект равен null.
●​ assertNotNull(object) — проверяет, что объект не равен null

78.​JUnit аннотации @Test, @DisplayName.


Аннотация @Test
Указывает, что метод является тестовым. Не объявляет никаких атрибутов.
Используются утверждения (assertions) для проверки правильности
выполнения кода (например, assertEquals, assertTrue).
Такие методы наследуются, если не переопределены.

Аннотация @DisplayName
Объявляет пользовательское имя для отображения класса или метода
тестирования(могут содержать пробелы, специальные символы и даже
эмодзи). Такие аннотации не наследуются.

79.​JUnit аннотации @BeforeEach, @AfterEach.


Аннотации @BeforeEach и @AfterEach использование в библиотеке JUnit для
подготовки и выполнения тестов. Они позволяют определять методы, которые
будут автоматически включаться до и после каждого тестового метода в
тестовом классе.

Особенности :

1.​ Замена аннотации @Before и @After из JUnit 4.

2.​ Метод НЕ ДОЛЖЕН быть статическим, иначе возникнет ошибка при


выполнении.

3.​ Методы @BeforeEach и @AfterEach из родительских классов


наследуются дочерними классами, если они не переопределены.

Аннотация @BeforeEach используется для обозначения того, что


аннотированный метод должен выполняться перед каждым методом @Test,
@RepeatedTest, @ParameterizedTest, или @TestFactory в текущем классе.

По умолчанию тестовые методы будут выполняться в том же потоке, что и


аннотированный @BeforeEach метод.

Использование @BeforeEach

Добавьте аннотацию @BeforeEach к методу, как указано ниже:

@BeforeEach

public void initEach(){

//test setup code

@Test

void succeedingTest() {
//test code and assertions

Аннотация @AfterEach используется для обозначения того, что


аннотированный метод должен выполняться после каждого метода, помеченного
@Test, @RepeatedTest, @ParameterizedTest, или @TestFactory в текущем классе.

По умолчанию тестовые методы будут выполняться в том же потоке, что и


аннотированный @AfterEach метод.

Использование @AfterEach

Добавьте аннотацию @AfterEach к методу, как указано ниже:

@AfterEach

public void cleanUpEach(){

//Test cleanup code

@Test

void succeedingTest() {

//test code and assertions

Особенности наследования

●​ Методы @BeforeEach и @AfterEach из родительских классов проводятся


для испытаний в дочерних классах, если они не переопределены.

●​ Последовательность выполнения:

@BeforeEach из родительского класса → @BeforeEach из дочернего класса →


тестовый метод → @AfterEach из дочернего класса → @AfterEach из
родительского класса.

Практическое применение
●​ @BeforeEach обычно используется для подготовки данных, организации
объектов или настройки независимых зависимостей.

●​ @AfterEach подает заявку на освобождение ресурсов, таких как закрытие


соединений с базой данных, удаление временных файлов и т. д. д.

80.​Тестовые классы и методы JUnit.


JUnit — это популярный фреймворк для модульного тестирования в Java. Он
позволяет разработчикам писать и выполнять тесты для проверки корректности
работы их кода. JUnit предоставляет аннотации и методы, которые упрощают
процесс написания тестов и управления ими.

Основные аннотации JUnit

1.​ @Test: Эта аннотация используется для обозначения метода как


тестового. JUnit будет выполнять этот метод как тест.

2.​ @Before: Этот метод будет выполняться перед каждым тестом. Он часто
используется для настройки тестовой среды.

3.​ @After: Этот метод будет выполняться после каждого теста. Он может
использоваться для очистки ресурсов или сброса состояния.

4.​ @BeforeClass: Этот метод будет выполняться один раз перед


выполнением всех тестов в классе. Он должен быть статическим.

5.​ @AfterClass: Этот метод будет выполняться один раз после выполнения
всех тестов в классе. Он также должен быть статическим.

6.​ @Ignore: Эта аннотация используется для временного игнорирования


теста. Тест, помеченный этой аннотацией, не будет выполняться.

7.​ @ParameterizedTest: Эта аннотация используется для


параметризованных тестов, позволяя запускать один и тот же тест с
различными наборами данных.
81.​Утверждения JUnit. Класс Assert.
Ассерты (asserts) — это специальные проверки, которые можно вставить в
разные места кода. Их задача определять, что что-то пошло не так.

Основной целью тестирования является проверка того, что код работает корректно, а
утверждения (assertions) позволяют сравнивать ожидаемый и фактический результат.

В JUnit для проверки условий используется класс


org.junit.jupiter.api.Assertions (в JUnit 5) или org.junit.Assert (в JUnit
4).

Функция JUnit 4 JUnit 5

Аннотация для @Test (из org.junit) @Test (из


теста org.junit.jupiter.api)
Утверждения org.junit.Assert.* org.junit.jupiter.api.Assertions
.*

Группировка Отсутствует assertAll()

Проверка Аннотация Метод assertThrows()


исключений @Test(expected=Exception)

82.​Тестирование исключений JUnit.


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

1. Использование @Test(expected = Exception.class) (JUnit 4)

При помощи аннотации @Test можно указать ожидаемый тип исключения. Если метод
выбрасывает указанное исключение, тест считается успешным.

2. Использование блока try-catch

Этот способ позволяет проверить как факт выбрасывания исключения, так и его
содержимое (например, сообщение).

3. Использование assertThrows (JUnit 5)

JUnit 5 предоставляет метод Assertions.assertThrows, который делает


тестирование исключений удобным и читаемым.

4. Проверка исключений с использованием библиотеки AssertJ

Если используется библиотека AssertJ, можно ещё более лаконично проверять


исключения.

83.​Генератор документирования Javadoc. Виды комментариев.

можете обратиться к вопросу 6

Комментарии в Java бывают трех видов:


➢​Однострочные комментарии начинаются с //. После этих двух
символов может следовать любой текст, вся строка не будет
анализироваться и исполняться.

➢​Многострочные комментарии начинаются с /* и заканчиваются на


*/. Принято каждую строку начинать с символа *, хотя технически
это и необязательно:

➢​Документирующие комментарии начинаются с /** и заканчиваются


на */. Уже для них обязательно каждую строку начинать с символа *.​
Документирующие комментарии — это подвид многострочных. При
этом несут дополнительную функцию — их можно собрать при
помощи специальной утилиты javadoc и выдать в качестве
документации к вашему коду.

Javadoc — это инструмент для автоматической генерации документации в


Java. Он позволяет извлекать комментарии из исходного кода и
формировать HTML-документацию.

Дескрипторы Javadoc:

Форма документирования кода:

Документирование класса, метода или переменной начинается с


комбинации символов /** , после которого следует тело комментариев;
заканчивается комбинацией символов */.

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


дескриптор, начинающийся с символа '@' должен стоять первым в строке.
Несколько дескрипторов одного и того же типа необходимо группировать
вместе. Встроенные дескрипторы (начинаются с фигурной скобки) можно
помещать внутри любого описания.

Пример:
/**
* Класс продукции со свойствами <b>maker</b> и <b>price</b>.
* @autor NN
* @version 2.1
*/
class Product
{
/** Поле производитель */
private String maker;

/** Поле цена */


public double price;

/**
* Конструктор - создание нового объекта
* @see Product#Product(String, double)
*/
Product()
{
setMaker("");
price=0;
}

/**
* Конструктор - создание нового объекта с определенными значениями
* @param maker - производитель
* @param price - цена
* @see Product#Product()
*/
Product(String maker,double price){
this.setMaker(maker);
this.price=price;
}

/**
* Функция получения значения поля {@link Product#maker}
* @return возвращает название производителя
*/
public String getMaker() {
return maker;
}

/**
* Процедура определения производителя {@link Product#maker}
* @param maker - производитель
*/
public void setMaker(String maker) {
this.maker = maker;
}
}
84.​Дескрипторы Javadoc.

Дескрипторы Javadoc — это специальные аннотации или теги, которые


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

Дескрипторы Javadoc начинаются с символа @ и располагаются в


комментариях вида /** ... */. Ниже приведен список часто используемых
дескрипторов Javadoc:

Дескриптор Описание Применим к

@author Автор Класс, интерфейс

@version Версия. Не более одного Класс, интерфейс


дескриптора на класс.

@since Указывает, с какой версии Класс, интерфейс, поле, метод


доступно.

@see Ссылка на другое место в Класс, интерфейс, поле, метод


документации.

@param Входной параметр метода. Метод

@return Описание возвращаемого Метод


значения.

@deprecated Описание устаревших блоков Класс, интерфейс, поле, метод


кода.
{@link reference} Ссылка. Класс, интерфейс, поле, метод

{@value} Описание значения переменной. Статичное поле

пример класса
Задачи
1.​ Условие: «Реализовать программу для выполнения следующих
математических операций с целочисленным, байтовым и
вещественным типами данных: сложение, вычитание, умножение,
деление, деление по модулю (остаток), модуль числа, возведение в
степень. Все данные вводятся с клавиатуры (класс Scanner, System.in,
nextint).» По данному условию необходимо реализовать программу с
интерактивным консольным меню, (т.е. вывод списка действий по
цифрам. При этом при нажатии на цифру у нас должно выполняться
определенное действие). При этом в программе данные пункты
должны называться следующим образом:
a.​ Вывести все таблицы из MySQL.
b.​ Создать таблицу в MySQL.
c.​ Сложение чисел, результат сохранить в MySQL с
последующим выводом в консоль.
d.​ Вычитание чисел, результат сохранить в MySQL с
последующим выводом в консоль.
e.​ Умножение чисел, результат сохранить в MySQL с
последующим выводом в консоль.
f.​ Деление чисел, результат сохранить в MySQL с последующим
выводом в консоль.
g.​ Деление чисел по модулю (остаток), результат сохранить в
MySQL с последующим выводом в консоль.
h.​ Возведение числа в модуль, результат сохранить в MySQL с
последующим выводом в консоль.
i.​ Возведение числа в степень, результат сохранить в MySQL с
последующим выводом в консоль.
j.​ Сохранить все данные (вышеполученные результаты) из
MySQL в Excel и вывести на экран.
https://github.com/AliceAnd0/java_exam/tree/main/NumbersInDB

2.​ Напишите программу, в которой из строки "I have 3 cats, 4 dogs, and 1
turtle" отбираются цифры. Из этих цифр формируется массив.
https://github.com/polinatut/exem_java/blob/main/ex_2/ExtractNumbers.java
3.​ Разработайте программу, которая выводит в консоль все цифры,
входящие в натуральное число n. К примеру, если дано число 2359,
то в консоль выводятся отдельно числа 2, 3, 5, 9.
https://github.com/mirrrler/task3

4.​ Написать калькулятор для строковых выражений вида "<число>


<операция> <число>", где <число> - положительное целое число
меньшее 10, записанное словами, например, "четыре",
<арифметическая операция> - одна из операций "плюс", "минус",
"умножить". Результат выполнения операции вернуть в виде
текстового представления числа. Пример: "пять плюс четыре" -->
"девять".
https://github.com/dariadegt/java_exam/blob/main/Task_4.java

5.​ Напишите программную реализацию бинарного дерева поиска.


https://github.com/gavalone/for_work/blob/main/src/Task_5.java

6.​ Разработайте программу, которая выводит буквы английского


алфавита, используя цикл while в MySQL/PostgreSQL.
https://github.com/bshkrrr/java_exam/tree/main/src/main/java/com/example/demo

7.​ Напишите программу, которая будет выводить в консоль введенное


слово 6 раз и сохранять в MySQL/PostgreSQL.
https://github.com/flamingo99900/JavaEkz/tree/task_7

8.​ Разработать программу для вывода на экран кубов первых десяти


положительных чисел.
https://github.com/gavalone/for_work/blob/main/src/Task_8.java

9.​ Напишите программу, которая по дате определяет день недели, на


который эта дата приходится.
https://github.com/itsvakonst/javaexam/blob/main/Task9.java

10.​Написать класс, который при введении даты в формате ДД.ММ.ГГ (к


примеру, 22.10.20) выводит номер недели. Даты начиная с 2020 по
2022 годы. К примеру, первая неделя в 2020 году: 1-5 января, вторая
неделя – 6-12 января. Значит при вводе 08.01.20 вывод должен быть:
Неделя 2.

https://github.com/Delia0001/java_exam/blob/main/Task_10.java
11.​Разработайте программу, реализующую рекурсивное вычисление
факториала.
https://github.com/NafaNaniz/exam/blob/main/RecursiveFactorial.java

12.​Разработать класс-оболочку для числового типа double. Реализовать


статические методы сложения, деления, возведения в степень.
https://github.com/AliceAnd0/java_exam/blob/main/DoubleWrapper.java

13.​Разработать программу, которая заполняет двумерный массив


случайными положительными числами в диапазоне от 1 до 100 до
тех пор, пока сумма граничных элементов не станет равной 666.
Пользователь вначале вводит размер матрицы.
https://github.com/polinatut/exem_java/blob/main/ex_13/MatrixSum.java

14.​Разработать программу, в которой требуется создать класс,


описывающий геометрическую фигуру – треугольник. Методами
класса должны быть – вычисление площади, периметра. Создать
класс-наследник, определяющий прямоугольный треугольник.
https://github.com/mirrrler/task14

15.​Разработать программу, в которой требуется создать абстрактный


класс. В этом абстрактном классе определить абстрактные методы
вычисления функции в определенной точке. Создать
классы-наследники абстрактного класса, описывающими уравнения
прямой и параболы. Программа должна выводить в консоль значение
функции при вводе определенного значения.
https://github.com/dariadegt/java_exam/blob/main/Task_15.java

16.​Создать интерфейс Progress c методами вычисления любого


элемента прогрессии и суммы прогрессии. Разработать классы
арифметической и геометрической прогрессии, которые
имплементируют интерфейс Progress.
https://github.com/max33128/tasks

17.​Разработать интерфейс InArray, в котором предусмотреть метод


сложения двух массивов. Создать класс ArraySum, в котором
имплементируется метод сложения массивов. Создать класс OrArray,
в котором метод сложения массивов имплементируется как
логическая операция ИЛИ между элементами массива.
https://github.com/bshkrrr/java_exam/tree/main/src/main/java/com/example/demo
18.​Создать класс Binary для работы с двоичными числами
фиксированной длины. Число должно быть массивом тип char,
каждый элемент которого принимает значение 0 или 1. Младший бит
имеет младший индекс. Отрицательные числа представляются в
дополнительном коде. Дополнительный код получается инверсией
всех битов с прибавлением 1 к младшему биту. Например, +1 – это в
двоичном коде будет выглядеть, как 0000 0001. А -1 в двоичном коде
будет выглядеть, как 1111 1110 + 0000 0001 = 1111 1111. Создать
методы конвертации десятичного числа в массив и обратно.
https://github.com/flamingo99900/JavaEkz/tree/task_18

19.​Создать класс Matrix для работы с двумерными матрицами. Создать


методы для генерации нулевой матрицы, а также для генерации
матрицы со случайными величинами – применить Math.random().
Реализовать метод сложения матриц.
https://github.com/gavalone/for_work/blob/main/src/Matrix.java

20.​Реализовать класс MyMath для работы с числами. Реализовать


статический метод класса MyMath.round(), который округляет дробь
до целого числа. Также статический метод abs(), который находит
модуль числа. Статический метод MyMath.pow() для нахождения
степени числа. Библиотеку Math не использовать.
https://github.com/itsvakonst/javaexam/blob/main/Task20.java

21.​Разработать программу для игры «Угадайка». Программа загадывает


случайное число от 1 до 10, требуется его отгадать с трех попыток.
После каждой попытки, если результат неверен, игроку выводится
сообщение, меньше или больше названное игроком число, чем
загаданное. Сет заканчивается или если игрок угадывает число, или
если исчерпывает три попытки, не угадав. Игра должна быть
выполнена в бесконечном цикле, и продолжается до тех пор, пока на
предложение «Сыграем еще раз?» игрок не напишет «Нет».
https://github.com/Delia0001/java_exam/blob/main/Task_21.java

22.​Разработайте программу-генератор рабочего календаря. Слесарь


механосборочного цеха работает сутки через трое. Если смена
попадает на воскресенье, то переносится на понедельник. По
введенной дате программа должна генерировать расписание из дат
на текущий месяц на 2022 год.
https://github.com/NafaNaniz/exam/blob/main/WorkScheduleGenerator.java
23.​Разработать класс для представления комплексных чисел с
возможностью задания вещественной и мнимой частей в виде
массива из двух чисел типа int. Определить методы для выполнения
операций сложения, вычитания и умножения комплексных чисел.
https://github.com/AliceAnd0/java_exam/blob/main/ComplexNumber.java

24.​Создайте класс Form - оболочку для создания и ввода пароля. Он


должен иметь методы input, submit, password. Создайте класс
SmartForm, который будет наследовать от Form и сохранять значения
password.
https://github.com/polinatut/exem_java/tree/main/ex_24

25.​Сделайте класс User, в котором будут следующие protected поля -


name (имя), age (возраст), public методы setName, getName, setAge,
getAge. Сделайте класс Worker, который наследует от класса User и
вносит дополнительное private поле salary (зарплата), а также
методы public getSalary и setSalary. Создайте объект этого класса
'Иван', возраст 25, зарплата 1000. Создайте второй объект этого
класса 'Вася', возраст 26, зарплата 2000. Найдите сумму зарплата
Ивана и Васи. Сделайте класс Student, который наследует от класса
User и вносит дополнительные private поля стипендия, курс, а также
геттеры и сеттеры для них.
https://github.com/mirrrler/task25

26.​Создайте класс ColorModel для определения цветовой модели.


Разработайте подклассы RGBconverter и CMYKconverter для
конвертации цвета из одной модели в другую. Конвертация CMYK в
RGB производится по следующим формулам: R = 255 × (1-C) ×
(1-K), G = 255 × (1-M) × (1-K), B = 255 × (1-Y) × (1-K) (где R – red, G
– green, B – black, C – Cyan, M - Magenta, Y - Yellow, K- Black))
https://github.com/dariadegt/java_exam/blob/main/Task_26.java

27.​Создайте класс Number для конвертации десятичного числа в


бинарный, восьмеричный, шестнадцатеричный вид. Реализовать в
виде статических методов класса. Числа вводятся с клавиатуры с
запросом в какой численный вид конвертировать.
https://github.com/gavalone/for_work/blob/main/src/Number.java

28.​Разработать класс Neuron для реализации нейронной сети из двух


нейронов и одного выхода. Сделать функцию прямого
распространения с функцией активации в виде сигмоиды.
не стала даже комменты убирать чтобы хоть чето было понятно
https://github.com/bshkrrr/java_exam/tree/main/src/main/java/com/example/demo

29.​Напишите программу, которая заполняет списочный массив


случайными числами типа Integer (значения этих чисел были от 1 до
100). Список должен содержать 100 элементов. Затем отсортируйте
по убыванию список и выведите первые 10 значений в консоль.
Результаты сохраните в MySQL/PostgreSQL.
https://github.com/flamingo99900/JavaEkz/tree/task_29

30.​Разработайте программу, которая заполняет список случайными


числами. Количество элементов и числовой диапазон вводятся
пользователем. Программа должна проверять, входит ли число
(также вводится пользователем) в данный список. Должен быть
реализован бинарный поиск. Результаты должны сохраняться в
MySQL/PostgreSQL и выводиться оттуда же.
https://github.com/max33128/tasks

31.​На основе класса BitSet разработайте программу для реализации


битовых операций AND, OR, XOR, а также маскирования.
https://github.com/itsvakonst/javaexam/blob/main/Task31.java

32.​Напишите программу, которая получает в качестве входных данных


два числа. Эти числа являются количество строк и столбцов
двумерной коллекции целых чисел. Далее элементы заполняются
случайными числами и выводятся в консоль в виде таблицы.
https://github.com/Delia0001/java_exam/blob/main/Task_32.java

33.​Разработайте программу, которая получает в качестве параметра два


числа –количество строк и столбцов двумерной коллекции целых
чисел. Коллекция заполняется случайными числами, после чего на
экран выводятся максимальное и минимальное значения с
индексами ячеек.
https://github.com/NafaNaniz/exam/blob/main/Array2D.java

34.​Разработайте программу, в которой создайте две коллекции с


именами людей (строковые переменные). Результат сохранить в
MySQL/PostgreSQL. Затем последовательно выводите в консоль
имена.
https://github.com/AliceAnd0/java_exam/tree/main/NamesToDB
35.​Напишите программу, которая реализует класс Matrix и следующие
методы:
a.​ Сложение и вычитание матриц.
b.​ Умножение матрицы на число.
c.​ Произведение двух матриц.
d.​ Транспонированная матрица.
e.​ Возведение матрицы в степень.
f.​ Если метод, возвращает матрицу, то он должен возвращать
новый объект, а не менять базовый.
​ https://github.com/polinatut/exem_java/tree/main/ex_35

36.​Разработать программу для поочередной обработки текстовых


файлов. Файлы созданы со следующими именами: n.txt, где n –
натуральное число. В файлах записаны: в первой строке одно число
с плавающей запятой, во второй строке – второе число. Пользователь
вводит название файла и требуемую операцию над числами
(сложение, умножение, разность). Результат выводится на экран и
файл n_out.txt.
https://github.com/mirrrler/task36

37.​Написать приложение для сложения, вычитания, умножения,


деления, возведения в степень логарифмов. Программа должна
выполнять ввод данных, проверку правильности введенных данных,
выдачу сообщений в случае ошибок. Результат выводится на экран и
записывается в файл.
https://github.com/dariadegt/java_exam/blob/main/Task_37.java

38.​Разработать программу шифровки-дешифровки по алгоритму


AES-128. Данные берутся из файла, зашифрованные данные
сохраняются в указанный файл.
https://github.com/gavalone/for_work/blob/main/src/Task_38.java

39.​Разработать программу нахождения наибольшего общего делителя


двух натуральных чисел. Требуется реализовать рекурсивный и без
рекурсии варианты. Результат сохранить в MySQL/PostgreSQL.
https://github.com/bshkrrr/java_exam/tree/main/src/main/java/com/example/demo
40.​Напишите программу, которая каждые 5 секунд отображает на
экране данные о времени, прошедшем от начала запуска программы,
а другой её поток выводит сообщение каждые 7 секунд. Третий
поток выводит на экран сообщение каждые 10 секунд. Программа
работает одну минуту, затем останавливается. Все результаты после
вывода необходимо сохранить в MySQL/PostgreSQL.
https://github.com/flamingo99900/JavaEkz/tree/task_40

41.​Условие задачи: «Ввести две строки (не менее 50 символов каждая) с


клавиатуры. Необходимо вывести на экран две введенных ранее
строки, подсчитать и вывести размер длины каждой строки,
объединить данные строки в одну, сравнить данные строки и
результат сравнения вывести на экран». По данному условию
необходимо реализовать программу с интерактивным консольным
меню, (т.е. вывод списка действий по цифрам. При этом при нажатии
на цифру у нас должно выполняться определенное действие). При
этом в программе данные пункты должны называться следующим
образом:
a.​ Вывести все таблицы из MySQL.
b.​ Создать таблицу в MySQL.
c.​ Ввести две строки с клавиатуры, результат сохранить в MySQL
с последующим выводом в консоль.
d.​ Подсчитать размер ранее введенных строк, результат
сохранить в MySQL с последующим выводом в консоль.
e.​ Объединить две строки в единое целое, результат сохранить в
MySQL с последующим выводом в консоль.
f.​ Сравнить две ранее введенные строки, результат сохранить в
MySQL с последующим выводом в консоль.
g.​ Сохранить все данные (вышеполученные результаты) из
MySQL в Excel и вывести на экран.
https://github.com/max33128/tasks
42.​Написать на основе Spring Boot клиент-серверное приложение
MyUser, в котором можно управлять данными пользователей из базы
данных через веб-интерфейс: имя, фамилия, возраст, номер группы.
База данных может быть любой – MySQL, PostgreSQL и т.д. При
этом должна быть доступна возможность
добавления/удаления/редактирования пользователей.
https://github.com/itsvakonst/javaexam/tree/main/Task42/main

43.​Написать на основе Spring Boot Security форму для авторизации и


регистрации пользователя. При этом после авторизации
пользователя должно быть перенаправление на главную страницу.
Главная страница должна содержать запись «Hello World!». При этом
до авторизации главная страница не должна быть доступна для
пользователя.
Код из main: https://github.com/Delia0001/java_exam/tree/main/Task43/main
Весь проект в формате zip:
https://github.com/Delia0001/java_exam/blob/main/task_43.zip

44.​Разработать MVC-приложение арифметический калькулятор на


основе Spring Boot. Применить шаблонизатор Thymeleaf. Все
результаты вычисления должны сохраняться и выводиться из
MySQL.
https://github.com/NafaNaniz/calc

45.​Разработка веб-MVC приложения на основе Spring Boot.


Приложение должно генерировать последовательность из 1000
случайных чисел в диапазоне, заданном пользователем, и выводит
эти числа на экран и вычисляет их среднее арифметическое.
https://github.com/AliceAnd0/java_exam/tree/main/WebMVCRandomNumbers

46.​Разработать приложение для работы с локальной базой данных


MySQL. Создайте базу данных мобильных телефонов (не менее 10
позиций), со следующими полями: производитель, модель, год
выпуска, диагональ экрана. Напишите методы для выполнения
запросов к базе данных. Все данные должны выводиться в консоли
на экран.
https://github.com/polinatut/exem_java/tree/main/ex_46

Вам также может понравиться