Forwarded from ChatRoom (Java for Beginner) (Первожрец Java)
А есть еще желающие активно поучаствовать в учебной разработке приложения на Spring? Пишите! 😉
Please open Telegram to view this post
VIEW IN TELEGRAM
Что выведет код?
#Tasks
public class Task240625 {
public static void main(String[] args) {
String s = null;
s = s + "Java";
System.out.println(s);
}
}
#Tasks
Варианты ответа:
Anonymous Quiz
7%
null
45%
"Java"
24%
"nullJava"
24%
Ошибка выполнения (NullPointerException)
Продолжаем выбирать темы для разбора и голосовать за рассмотрение предложенных! 🤓
Голосуем за тему к рассмотрению в эти выходные!
Выбираем новую тему!
(можете предложить что-то из того, что предлагали на прошлой и позапрошлых неделях и что проиграло в голосовании!)
Не стесняемся!✌️
Голосуем за тему к рассмотрению в эти выходные!
Выбираем новую тему!
(можете предложить что-то из того, что предлагали на прошлой и позапрошлых неделях и что проиграло в голосовании!)
Не стесняемся!
Please open Telegram to view this post
VIEW IN TELEGRAM
Что такое deadlock и как его избежать? 🤓
Ответ:
Deadlock (взаимная блокировка) возникает, когда два или более потока ждут друг друга для освобождения ресурсов.
Пример:
поток A ждет ресурс X, удерживая Y, а поток B ждет Y, удерживая X.
Избежать можно:
- Упорядочивая захват ресурсов.
- Используя тайм-ауты (tryLock в Lock).
- Минимизируя области синхронизации.
Пример упорядочивания:
synchronized (resource1) {
synchronized (resource2) {
// Работа с ресурсами
}
}
#собеседование
Ответ:
Пример:
поток A ждет ресурс X, удерживая Y, а поток B ждет Y, удерживая X.
Избежать можно:
- Упорядочивая захват ресурсов.
- Используя тайм-ауты (tryLock в Lock).
- Минимизируя области синхронизации.
Пример упорядочивания:
synchronized (resource1) {
synchronized (resource2) {
// Работа с ресурсами
}
}
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
Руководство по POM (Project Object Model) в Maven
POM (Project Object Model) является основой любого Maven-проекта. Файл pom.xml определяет структуру проекта, его зависимости, процесс сборки и другие аспекты, необходимые для управления жизненным циклом проекта. Этот документ представляет собой XML-файл, который Maven интерпретирует для создания модели проекта в памяти.
Основные теги
Основные теги pom.xml формируют базовую идентификацию и структуру проекта. Они обязательны или критически важны для корректной работы Maven.
<project>: Корневой элемент каждого pom.xml. Он определяет пространство имен XML (xmlns) и схему (xsi:schemaLocation), чтобы Maven мог валидировать файл. Все остальные элементы являются дочерними для <project>. В памяти Maven создает объект Project, который хранит всю информацию о проекте, включая зависимости, плагины и настройки сборки.
<modelVersion>: Указывает версию модели POM, используемой в файле. На момент 2025 года стандартной является версия 4.0.0. Этот тег необходим, так как Maven использует его для определения правил парсинга и совместимости. Неправильная версия приведет к ошибке парсинга.
<groupId>: Уникальный идентификатор группы, к которой относится проект. Обычно это доменное имя компании или организации в обратном порядке (например, com.example). В памяти Maven использует groupId как часть координат для идентификации артефакта в репозитории.
<artifactId>: Уникальное имя артефакта внутри группы. Это название проекта или модуля (например, my-app). Вместе с groupId и version формирует уникальные координаты артефакта.
<version>: Версия проекта. Следует семантическому версионированию (например, 1.0.0-SNAPSHOT). Maven использует версию для управления артефактами в локальном и удаленных репозиториях. Суффикс SNAPSHOT указывает на нестабильную версию, что влияет на поведение кэширования.
<packaging>: Определяет тип выходного артефакта (например, jar, war, pom). По умолчанию — jar. Этот тег влияет на жизненный цикл сборки, так как Maven выбирает соответствующие плагины и цели (goals) для обработки. Например, для war подключается плагин maven-war-plugin.
Эти теги формируют минимальный pom.xml. Maven парсит их в объектную модель, которая хранится в памяти JVM во время выполнения. Объектная модель включает org.apache.maven.model.Model, где каждый тег маппится на соответствующее поле или коллекцию. Например, groupId, artifactId и version объединяются в уникальный ключ артефакта.
Расширенные теги
Расширенные теги добавляют метаданные, улучшающие документацию и управление проектом. Они необязательны, но полезны в корпоративных средах.
<name>: Человекочитаемое название проекта. Используется в отчетах и документации, генерируемых Maven (например, через maven-site-plugin). Не влияет на логику сборки, но хранится в метаданных артефакта.
<description>: Описание проекта. Как и <name>, используется для документации. Maven включает это поле в метаданные артефакта, которые публикуются в репозиторий.
<url>: URL проекта, например, сайт или репозиторий. Используется в документации и для генерации ссылок в отчетах.
<inceptionYear>: Год создания проекта. Это поле чисто информационное, хранится в метаданных.
<organization>: Содержит информацию об организации, включая <name> и <url>. Используется для единообразной документации в крупных проектах.
Эти теги не влияют на процесс сборки, но добавляются в файл метаданных артефакта (META-INF/maven/groupId/artifactId/pom.properties), который создается при упаковке. В памяти они хранятся как часть объекта Model, но не участвуют в логике выполнения.
#Java #middle #Maven #pom
POM (Project Object Model) является основой любого Maven-проекта. Файл pom.xml определяет структуру проекта, его зависимости, процесс сборки и другие аспекты, необходимые для управления жизненным циклом проекта. Этот документ представляет собой XML-файл, который Maven интерпретирует для создания модели проекта в памяти.
Основные теги
Основные теги pom.xml формируют базовую идентификацию и структуру проекта. Они обязательны или критически важны для корректной работы Maven.
<project>: Корневой элемент каждого pom.xml. Он определяет пространство имен XML (xmlns) и схему (xsi:schemaLocation), чтобы Maven мог валидировать файл. Все остальные элементы являются дочерними для <project>. В памяти Maven создает объект Project, который хранит всю информацию о проекте, включая зависимости, плагины и настройки сборки.
<modelVersion>: Указывает версию модели POM, используемой в файле. На момент 2025 года стандартной является версия 4.0.0. Этот тег необходим, так как Maven использует его для определения правил парсинга и совместимости. Неправильная версия приведет к ошибке парсинга.
<groupId>: Уникальный идентификатор группы, к которой относится проект. Обычно это доменное имя компании или организации в обратном порядке (например, com.example). В памяти Maven использует groupId как часть координат для идентификации артефакта в репозитории.
<artifactId>: Уникальное имя артефакта внутри группы. Это название проекта или модуля (например, my-app). Вместе с groupId и version формирует уникальные координаты артефакта.
<version>: Версия проекта. Следует семантическому версионированию (например, 1.0.0-SNAPSHOT). Maven использует версию для управления артефактами в локальном и удаленных репозиториях. Суффикс SNAPSHOT указывает на нестабильную версию, что влияет на поведение кэширования.
<packaging>: Определяет тип выходного артефакта (например, jar, war, pom). По умолчанию — jar. Этот тег влияет на жизненный цикл сборки, так как Maven выбирает соответствующие плагины и цели (goals) для обработки. Например, для war подключается плагин maven-war-plugin.
Эти теги формируют минимальный pom.xml. Maven парсит их в объектную модель, которая хранится в памяти JVM во время выполнения. Объектная модель включает org.apache.maven.model.Model, где каждый тег маппится на соответствующее поле или коллекцию. Например, groupId, artifactId и version объединяются в уникальный ключ артефакта.
Расширенные теги
Расширенные теги добавляют метаданные, улучшающие документацию и управление проектом. Они необязательны, но полезны в корпоративных средах.
<name>: Человекочитаемое название проекта. Используется в отчетах и документации, генерируемых Maven (например, через maven-site-plugin). Не влияет на логику сборки, но хранится в метаданных артефакта.
<description>: Описание проекта. Как и <name>, используется для документации. Maven включает это поле в метаданные артефакта, которые публикуются в репозиторий.
<url>: URL проекта, например, сайт или репозиторий. Используется в документации и для генерации ссылок в отчетах.
<inceptionYear>: Год создания проекта. Это поле чисто информационное, хранится в метаданных.
<organization>: Содержит информацию об организации, включая <name> и <url>. Используется для единообразной документации в крупных проектах.
Эти теги не влияют на процесс сборки, но добавляются в файл метаданных артефакта (META-INF/maven/groupId/artifactId/pom.properties), который создается при упаковке. В памяти они хранятся как часть объекта Model, но не участвуют в логике выполнения.
#Java #middle #Maven #pom
Работа с <properties>
Тег <properties> позволяет определять пользовательские переменные, которые можно использовать в других частях pom.xml. Это улучшает читаемость и упрощает управление конфигурацией.
Пример:
Переменные используются через синтаксис ${property.name}.
Например:
Maven при парсинге pom.xml заменяет все ${...} на соответствующие значения. Это происходит на этапе создания модели в памяти. Если свойство не найдено, Maven пытается использовать системные свойства JVM или переменные окружения. Если и это не удается, сборка завершится ошибкой.
Свойства также могут быть переопределены через командную строку:
В памяти свойства хранятся в объекте Properties внутри модели Model. Они доступны всем плагинам и процессам сборки.
Важный нюанс: свойства не наследуются автоматически в дочерних модулях, если они определены в <properties> родительского POM. Для этого нужно использовать <dependencyManagement> или <pluginManagement>.
<dependencies>: Управление зависимостями
Тег <dependencies> определяет библиотеки, необходимые проекту. Каждая зависимость описывается тегом <dependency> с обязательными полями groupId, artifactId и version.
Scope'ы зависимостей
Атрибут <scope> определяет область применения зависимости:
compile: Зависимость доступна для компиляции, тестирования и выполнения. Включается в итоговый артефакт (например, в jar). Это значение по умолчанию.
provided: Зависимость нужна для компиляции, но предоставляется средой выполнения (например, сервлет API в контейнере). Не включается в итоговый артефакт.
runtime: Зависимость нужна только во время выполнения (например, JDBC-драйвер). Не используется при компиляции.
test: Зависимость нужна только для тестирования (например, JUnit). Не включается в итоговый артефакт.
system: Указывает локальный путь к зависимости через <systemPath>. Используется редко, так как нарушает принцип переносимости.
import: Используется в <dependencyManagement> для импорта зависимостей из другого POM. Не добавляет зависимость напрямую.
Maven при разрешении зависимостей создает граф зависимостей в памяти (используя org.apache.maven.artifact.Artifact). Для каждого артефакта хранится его scope, что влияет на classpath для различных фаз сборки. Например, test зависимости добавляются только в classpath для фазы test.
Exclusions и конфликт зависимостей
Конфликты зависимостей возникают, когда разные версии одной и той же библиотеки включаются через транзитивные зависимости. Maven решает конфликты, выбирая ближайшую к корню графа версию (стратегия "nearest wins"). Это может привести к проблемам, если выбранная версия несовместима.
Для исключения нежелательных транзитивных зависимостей используется тег <exclusions>:
В памяти Maven модифицирует граф зависимостей, удаляя исключенные артефакты. Это происходит на этапе разрешения зависимостей (dependency:resolve).
Для диагностики конфликтов полезна команда:
#Java #middle #Maven #pom
Тег <properties> позволяет определять пользовательские переменные, которые можно использовать в других частях pom.xml. Это улучшает читаемость и упрощает управление конфигурацией.
Пример:
<properties>
<java.version>11</java.version>
<spring.version>5.3.10</spring.version>
</properties>
Переменные используются через синтаксис ${property.name}.
Например:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
Maven при парсинге pom.xml заменяет все ${...} на соответствующие значения. Это происходит на этапе создания модели в памяти. Если свойство не найдено, Maven пытается использовать системные свойства JVM или переменные окружения. Если и это не удается, сборка завершится ошибкой.
Свойства также могут быть переопределены через командную строку:
mvn clean install -Djava.version=17
В памяти свойства хранятся в объекте Properties внутри модели Model. Они доступны всем плагинам и процессам сборки.
Важный нюанс: свойства не наследуются автоматически в дочерних модулях, если они определены в <properties> родительского POM. Для этого нужно использовать <dependencyManagement> или <pluginManagement>.
<dependencies>: Управление зависимостями
Тег <dependencies> определяет библиотеки, необходимые проекту. Каждая зависимость описывается тегом <dependency> с обязательными полями groupId, artifactId и version.
Scope'ы зависимостей
Атрибут <scope> определяет область применения зависимости:
compile: Зависимость доступна для компиляции, тестирования и выполнения. Включается в итоговый артефакт (например, в jar). Это значение по умолчанию.
provided: Зависимость нужна для компиляции, но предоставляется средой выполнения (например, сервлет API в контейнере). Не включается в итоговый артефакт.
runtime: Зависимость нужна только во время выполнения (например, JDBC-драйвер). Не используется при компиляции.
test: Зависимость нужна только для тестирования (например, JUnit). Не включается в итоговый артефакт.
system: Указывает локальный путь к зависимости через <systemPath>. Используется редко, так как нарушает принцип переносимости.
import: Используется в <dependencyManagement> для импорта зависимостей из другого POM. Не добавляет зависимость напрямую.
Maven при разрешении зависимостей создает граф зависимостей в памяти (используя org.apache.maven.artifact.Artifact). Для каждого артефакта хранится его scope, что влияет на classpath для различных фаз сборки. Например, test зависимости добавляются только в classpath для фазы test.
Exclusions и конфликт зависимостей
Конфликты зависимостей возникают, когда разные версии одной и той же библиотеки включаются через транзитивные зависимости. Maven решает конфликты, выбирая ближайшую к корню графа версию (стратегия "nearest wins"). Это может привести к проблемам, если выбранная версия несовместима.
Для исключения нежелательных транзитивных зависимостей используется тег <exclusions>:
<dependency>
<groupId>org.example</groupId>
<artifactId>lib-a</artifactId>
<version>1.0</version>
<exclusions>
<exclusion>
<groupId>org.unwanted</groupId>
<artifactId>unwanted-lib</artifactId>
</exclusion>
</exclusions>
</dependency>
В памяти Maven модифицирует граф зависимостей, удаляя исключенные артефакты. Это происходит на этапе разрешения зависимостей (dependency:resolve).
Для диагностики конфликтов полезна команда:
mvn dependency:tree
#Java #middle #Maven #pom
<dependencyManagement>: Централизованный контроль зависимостей
Тег <dependencyManagement> позволяет определять версии и настройки зависимостей, которые будут использоваться в проекте или его модулях. Это особенно полезно в многомодульных проектах.
Пример:
Зависимости из <dependencyManagement> не добавляются в проект автоматически. Они активируются только при указании groupId и artifactId в <dependencies> без версии. Это позволяет централизовать управление версиями в родительском POM.
В памяти Maven хранит эти зависимости в объекте DependencyManagement, который используется для разрешения версий при парсинге дочерних POM. Это снижает риск конфликтов версий в многомодульных проектах.
<build> и <plugins>
Тег <build> определяет процесс сборки проекта. Он включает настройки каталогов, плагинов и другие параметры.
Основные дочерние элементы:
<sourceDirectory>: Путь к исходному коду (по умолчанию src/main/java).
<testSourceDirectory>: Путь к тестам (по умолчанию src/test/java).
<resources>: Ресурсы, включаемые в артефакт.
<plugins>: Список плагинов для выполнения задач.
Пример плагина:
Каждый плагин привязан к фазам жизненного цикла Maven (например, compile, test, package). Плагины выполняются в JVM как отдельные классы, загружаемые через собственный класслоадер Maven. В памяти создается объект Plugin, содержащий конфигурацию и привязки к фазам.
Тег <pluginManagement> работает аналогично <dependencyManagement>, позволяя задавать конфигурацию плагинов для наследования в дочерних модулях.
<profiles>: Профили сборки
Профили позволяют настраивать сборку под разные окружения (например, dev, prod). Тег <profiles> содержит список <profile>.
Пример:
Профиль активируется через:
Командную строку: mvn clean install -Pdev.
Условия в <activation> (например, по OS, JDK или наличию файла).
Maven при парсинге объединяет активный профиль с основным pom.xml. Это происходит в памяти, где профиль мержится с моделью Model. Если несколько профилей активны, они применяются в порядке определения.
<repositories> и <pluginRepositories>
Теги <repositories> и <pluginRepositories> указывают, где Maven должен искать зависимости и плагины. По умолчанию используется центральный репозиторий Maven (https://repo.maven.apache.org/maven2).
Пример:
Maven загружает артефакты сначала из локального репозитория (~/.m2/repository), затем из указанных репозиториев. В памяти создается список объектов Repository, которые используются резолвером зависимостей.
#Java #middle #Maven #pom
Тег <dependencyManagement> позволяет определять версии и настройки зависимостей, которые будут использоваться в проекте или его модулях. Это особенно полезно в многомодульных проектах.
Пример:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.10</version>
</dependency>
</dependencies>
</dependencyManagement>
Зависимости из <dependencyManagement> не добавляются в проект автоматически. Они активируются только при указании groupId и artifactId в <dependencies> без версии. Это позволяет централизовать управление версиями в родительском POM.
В памяти Maven хранит эти зависимости в объекте DependencyManagement, который используется для разрешения версий при парсинге дочерних POM. Это снижает риск конфликтов версий в многомодульных проектах.
<build> и <plugins>
Тег <build> определяет процесс сборки проекта. Он включает настройки каталогов, плагинов и другие параметры.
Основные дочерние элементы:
<sourceDirectory>: Путь к исходному коду (по умолчанию src/main/java).
<testSourceDirectory>: Путь к тестам (по умолчанию src/test/java).
<resources>: Ресурсы, включаемые в артефакт.
<plugins>: Список плагинов для выполнения задач.
Пример плагина:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
Каждый плагин привязан к фазам жизненного цикла Maven (например, compile, test, package). Плагины выполняются в JVM как отдельные классы, загружаемые через собственный класслоадер Maven. В памяти создается объект Plugin, содержащий конфигурацию и привязки к фазам.
Тег <pluginManagement> работает аналогично <dependencyManagement>, позволяя задавать конфигурацию плагинов для наследования в дочерних модулях.
<profiles>: Профили сборки
Профили позволяют настраивать сборку под разные окружения (например, dev, prod). Тег <profiles> содержит список <profile>.
Пример:
<profiles>
<profile>
<id>dev</id>
<properties>
<env>development</env>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<env>production</env>
</properties>
</profile>
</profiles>
Профиль активируется через:
Командную строку: mvn clean install -Pdev.
Условия в <activation> (например, по OS, JDK или наличию файла).
Maven при парсинге объединяет активный профиль с основным pom.xml. Это происходит в памяти, где профиль мержится с моделью Model. Если несколько профилей активны, они применяются в порядке определения.
<repositories> и <pluginRepositories>
Теги <repositories> и <pluginRepositories> указывают, где Maven должен искать зависимости и плагины. По умолчанию используется центральный репозиторий Maven (https://repo.maven.apache.org/maven2).
Пример:
<repositories>
<repository>
<id>custom-repo</id>
<url>https://repo.example.com</url>
</repository>
</repositories>
Maven загружает артефакты сначала из локального репозитория (~/.m2/repository), затем из указанных репозиториев. В памяти создается список объектов Repository, которые используются резолвером зависимостей.
#Java #middle #Maven #pom
Parent POM'ы и наследование
Родительский POM позволяет централизовать конфигурацию для нескольких проектов.
Дочерний проект ссылается на родительский через <parent>:
Maven при парсинге загружает родительский POM и объединяет его с дочерним.
Наследуются:
- <dependencyManagement> и <pluginManagement>.
- <properties>.
- <repositories> и <pluginRepositories>.
В памяти создается композитная модель Model, где дочерний POM имеет приоритет над родительским. Это позволяет переопределять настройки. Однако <dependencies> и <plugins> не наследуются напрямую, чтобы избежать нежелательных включений.
Нюансы работы в памяти
Maven при запуске создает в JVM объектную модель проекта:
Парсинг pom.xml с помощью библиотеки plexus-utils и создание объекта org.apache.maven.model.Model.
Разрешение переменных ${...} с учетом <properties>, системных свойств и окружения.
Построение графа зависимостей с использованием Aether (библиотека для работы с репозиториями).
Создание плана выполнения (execution plan), где плагины привязываются к фазам жизненного цикла.
Каждый плагин выполняется в изолированном класслоадере, чтобы избежать конфликтов зависимостей. Локальный репозиторий (~/.m2/repository) кэширует артефакты, минимизируя сетевые запросы. Для SNAPSHOT-версий Maven периодически проверяет обновления в удаленных репозиториях.
#Java #middle #Maven #Pom
Родительский POM позволяет централизовать конфигурацию для нескольких проектов.
Дочерний проект ссылается на родительский через <parent>:
<parent>
<groupId>com.example</groupId>
<artifactId>parent-project</artifactId>
<version>1.0</version>
</parent>
Maven при парсинге загружает родительский POM и объединяет его с дочерним.
Наследуются:
- <dependencyManagement> и <pluginManagement>.
- <properties>.
- <repositories> и <pluginRepositories>.
В памяти создается композитная модель Model, где дочерний POM имеет приоритет над родительским. Это позволяет переопределять настройки. Однако <dependencies> и <plugins> не наследуются напрямую, чтобы избежать нежелательных включений.
Нюансы работы в памяти
Maven при запуске создает в JVM объектную модель проекта:
Парсинг pom.xml с помощью библиотеки plexus-utils и создание объекта org.apache.maven.model.Model.
Разрешение переменных ${...} с учетом <properties>, системных свойств и окружения.
Построение графа зависимостей с использованием Aether (библиотека для работы с репозиториями).
Создание плана выполнения (execution plan), где плагины привязываются к фазам жизненного цикла.
Каждый плагин выполняется в изолированном класслоадере, чтобы избежать конфликтов зависимостей. Локальный репозиторий (~/.m2/repository) кэширует артефакты, минимизируя сетевые запросы. Для SNAPSHOT-версий Maven периодически проверяет обновления в удаленных репозиториях.
#Java #middle #Maven #Pom
Что выведет код?
#Tasks
import java.util.function.Consumer;
public class Task250625 {
public static void main(String[] args) {
Consumer<String> c1 = s -> System.out.print("A" + s);
Consumer<String> c2 = s -> System.out.print("B" + s);
c1.andThen(c2).accept("1");
c2.andThen(c1).accept("2");
}
}
#Tasks
Что такое ThreadLocal? 🤓
Ответ:
ThreadLocal предоставляет каждой нити свою копию переменной, изолируя данные между потоками.
Полезно для хранения контекста, например, пользовательской сессии.
Пример:
ThreadLocal<Integer> threadId = ThreadLocal.withInitial(() -> Thread.currentThread().getId());
System.out.println(threadId.get());
// Уникальный ID для каждого потока
После использования нужно вызывать remove() для предотвращения утечек памяти.
#собеседование
Ответ:
Полезно для хранения контекста, например, пользовательской сессии.
Пример:
ThreadLocal<Integer> threadId = ThreadLocal.withInitial(() -> Thread.currentThread().getId());
System.out.println(threadId.get());
// Уникальный ID для каждого потока
После использования нужно вызывать remove() для предотвращения утечек памяти.
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM