Что такое Lock и чем он лучше synchronized? 🤓
Ответ:
Интерфейс Lock (например, ReentrantLock) предоставляет более гибкую синхронизацию, чем synchronized.
Поддерживает тайм-ауты (tryLock), неблокирующие операции и возможность прерывания.
Пример:
Lock lock = new ReentrantLock();
lock.lock();
try {
// Критическая секция
} finally {
lock.unlock();
}
В отличие от synchronized, Lock требует явного вызова unlock().
#собеседование
Ответ:
Поддерживает тайм-ауты (tryLock), неблокирующие операции и возможность прерывания.
Пример:
Lock lock = new ReentrantLock();
lock.lock();
try {
// Критическая секция
} finally {
lock.unlock();
}
В отличие от synchronized, Lock требует явного вызова unlock().
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
А вы знали, что первый компьютерный "контроллер версии" был создан в 1972 году?
Первыми системами контроля версий были SCCS (Source Code Control System) и RCS (Revision Control System). SCCS была разработана в 1972 году в Bell Labs и стала первой системой, которая позволяла отслеживать изменения в исходном коде. Эта система использовала простую модель хранения изменений, что делало её удобной для небольших проектов. RCS, появившаяся в 1982 году, улучшила функциональность SCCS и стала более популярной благодаря своей простоте и эффективности. RCS использовала концепцию "ревизий" и позволяла легко переключаться между различными версиями кода.
Proof
#facts
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
"Технологии без доверия пользователей — пустой звук."
Виктор Орловский, бывший CTO Сбербанка, сказал это в 2018 году на fintech-конференции в Москве.
Биография
#Citation #Biography
Please open Telegram to view this post
VIEW IN TELEGRAM
Wikipedia
Орловский, Виктор Михайлович
Виктор Орловский (род. 12 апреля 1974, Ташкент) — российский венчурный инвестор и предприниматель. Основатель и генеральный партнёр Fort Ross Ventures .
👍1
Null - отсутствие ссылки в Java
null в Java — это специальное зарезервированное значение, указывающее, что переменная-ссылка не указывает ни на один объект. Это важный элемент модели памяти Java, отражающий отсутствие объекта. null может быть присвоен любой переменной ссылочного типа: объекту, массиву, строке, интерфейсу и т.д.
Что такое null
Когда вы пишете:
Вы создаёте переменную name, которая не указывает на какой-либо объект в куче. Это эквивалентно "пустой" ссылке. Она существует, занимает место в стеке (как любая переменная), но не ссылается на объект в памяти.
Зачем нужен null
Обозначение "ничего"
Позволяет явно указать, что у переменной нет значения. Это особенно полезно, если объект должен быть присвоен позже или вычисляется по условию.
Инициализация по умолчанию
Все ссылки в Java по умолчанию равны null, если не инициализированы вручную.
Маркер отсутствия
null часто используется как сигнал того, что результат не найден, произошла ошибка, или объект ещё не готов.
Как работает null в памяти
Ссылочные переменные (например, Person person) хранятся в стеке.
Когда переменной присваивается null, это означает, что в ячейке стека отсутствует указатель на объект в куче.
Сам объект в куче при этом не создаётся или уже был уничтожен сборщиком мусора, если на него больше нет ссылок.
Здесь:
person — ячейка в стеке
Значение этой ячейки — специальное значение null (в JVM это просто 0 в ссылке)
Примеры использования
Плюсы использования null
Простота и ясность
Читабельный способ выразить "ничего", не создавая лишние объекты.
Низкие накладные расходы
Не требует выделения памяти в куче, что экономит ресурсы при инициализации.
Совместимость с другими системами
Многие API и базы данных возвращают null как знак "отсутствия значения".
Минусы и подводные камни
1. NullPointerException
Наиболее распространённая ошибка в Java — попытка вызвать метод или поле на null:
2. Неочевидность
Программа может работать "нормально", пока в какой-то момент не возникнет null в неожиданном месте. Это затрудняет отладку.
3. Проблемы при композиции
Методы, возвращающие null, требуют дополнительных проверок в вызывающем коде:
4. Не подходит для потокобезопасности
В многопоточных средах проверка на null может быть некорректной, если значение изменяется между проверкой и использованием.
Лучшие практики и альтернативы
Явная проверка на null
Использование Optional
Инициализация по умолчанию
Лучше избегать null, когда можно:
Контракты "никогда не null"
В современных проектах стараются придерживаться соглашения: параметры, возвращаемые значения и поля по умолчанию не null, если явно не сказано иное.
Специальные случаи и нюансы
Сравнение с null
Всегда используйте ==, а не equals() для сравнения с null.
Ссылочные типы и null
Массивы: могут быть null, отдельные элементы массива — тоже.
Строки: null — не то же самое, что пустая строка "".
Метод instanceof и null
null в параметрах
Вы можете передать null как аргумент в метод:
#Java #для_новичков #beginner #reference_types #null
null в Java — это специальное зарезервированное значение, указывающее, что переменная-ссылка не указывает ни на один объект. Это важный элемент модели памяти Java, отражающий отсутствие объекта. null может быть присвоен любой переменной ссылочного типа: объекту, массиву, строке, интерфейсу и т.д.
Что такое null
Когда вы пишете:
String name = null;
Вы создаёте переменную name, которая не указывает на какой-либо объект в куче. Это эквивалентно "пустой" ссылке. Она существует, занимает место в стеке (как любая переменная), но не ссылается на объект в памяти.
Зачем нужен null
Обозначение "ничего"
Позволяет явно указать, что у переменной нет значения. Это особенно полезно, если объект должен быть присвоен позже или вычисляется по условию.
Инициализация по умолчанию
Все ссылки в Java по умолчанию равны null, если не инициализированы вручную.
public class Example {
String name; // По умолчанию null
}
Маркер отсутствия
null часто используется как сигнал того, что результат не найден, произошла ошибка, или объект ещё не готов.
Как работает null в памяти
Ссылочные переменные (например, Person person) хранятся в стеке.
Когда переменной присваивается null, это означает, что в ячейке стека отсутствует указатель на объект в куче.
Сам объект в куче при этом не создаётся или уже был уничтожен сборщиком мусора, если на него больше нет ссылок.
Person person = null;
Здесь:
person — ячейка в стеке
Значение этой ячейки — специальное значение null (в JVM это просто 0 в ссылке)
Примеры использования
String userInput = null; // Пользователь ничего не ввёл
if (userInput == null) {
System.out.println("Пустой ввод");
}
List<String> list = getList();
if (list != null) {
list.add("new item");
}
Плюсы использования null
Простота и ясность
Читабельный способ выразить "ничего", не создавая лишние объекты.
Низкие накладные расходы
Не требует выделения памяти в куче, что экономит ресурсы при инициализации.
Совместимость с другими системами
Многие API и базы данных возвращают null как знак "отсутствия значения".
Минусы и подводные камни
1. NullPointerException
Наиболее распространённая ошибка в Java — попытка вызвать метод или поле на null:
String name = null;
System.out.println(name.length()); // NullPointerException
2. Неочевидность
Программа может работать "нормально", пока в какой-то момент не возникнет null в неожиданном месте. Это затрудняет отладку.
3. Проблемы при композиции
Методы, возвращающие null, требуют дополнительных проверок в вызывающем коде:
String result = compute();
if (result != null) {
...
}
Если забыть такую проверку — возможна ошибка.
4. Не подходит для потокобезопасности
В многопоточных средах проверка на null может быть некорректной, если значение изменяется между проверкой и использованием.
Лучшие практики и альтернативы
Явная проверка на null
Objects.requireNonNull(input, "Input must not be null");
Использование Optional
Optional<String> result = Optional.ofNullable(getName());
result.ifPresent(System.out::println);
Optional помогает избежать null, особенно в возвращаемых значениях.
Инициализация по умолчанию
Лучше избегать null, когда можно:
List<String> list = new ArrayList<>(); // вместо null
Контракты "никогда не null"
В современных проектах стараются придерживаться соглашения: параметры, возвращаемые значения и поля по умолчанию не null, если явно не сказано иное.
Специальные случаи и нюансы
Сравнение с null
if (obj == null) { ... }
Всегда используйте ==, а не equals() для сравнения с null.
obj.equals(null); // Может выбросить NPE, если obj == null
Ссылочные типы и null
Массивы: могут быть null, отдельные элементы массива — тоже.
Строки: null — не то же самое, что пустая строка "".
String s1 = null;
String s2 = "";
System.out.println(s1 == s2); // false
Метод instanceof и null
String s = null;
System.out.println(s instanceof String); // false
null в параметрах
Вы можете передать null как аргумент в метод:
printName(null);
Но важно, чтобы метод корректно это обрабатывал.
#Java #для_новичков #beginner #reference_types #null
👍4
Forwarded from ChatRoom (Java for Beginner) (Первожрец Java)
А есть еще желающие активно поучаствовать в учебной разработке приложения на Spring? Пишите! 😉
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1
Что выведет код?
#Tasks
public class Task240625 {
public static void main(String[] args) {
String s = null;
s = s + "Java";
System.out.println(s);
}
}
#Tasks
👍3
Варианты ответа:
Anonymous Quiz
12%
null
41%
"Java"
21%
"nullJava"
26%
Ошибка выполнения (NullPointerException)
😱1
Продолжаем выбирать темы для разбора и голосовать за рассмотрение предложенных! 🤓
Голосуем за тему к рассмотрению в эти выходные!
Выбираем новую тему!
(можете предложить что-то из того, что предлагали на прошлой и позапрошлых неделях и что проиграло в голосовании!)
Не стесняемся!✌️
Голосуем за тему к рассмотрению в эти выходные!
Выбираем новую тему!
(можете предложить что-то из того, что предлагали на прошлой и позапрошлых неделях и что проиграло в голосовании!)
Не стесняемся!
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Что такое 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
👍4
А вы знали, что термин "пиксель" был придуман в 1965 году?
Термин «пиксель» впервые появился в научной литературе в 1965 году благодаря Фредерику Биллингсли[3], сотруднику лаборатории реактивного движения. Он использовал это слово для обозначения графических компонентов в видеоданных, полученных с космических аппаратов, исследовавших Луну и Марс. Однако авторство термина принадлежит не Биллингсли. Он заимствовал его у Кита Макфарленда из компании Link Division of General Precision в Пало-Алто, который, в свою очередь, утверждал, что слово уже было в обиходе около 1963 года.
proof
#facts
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
"Интернет — это свобода, но свобода требует ответственности."
Евгений Чичваркин, сооснователь Евросети, сказал это в 2008 году в интервью о развитии e-commerce в России.
Биография
#Citation #Biography
Please open Telegram to view this post
VIEW IN TELEGRAM
Wikipedia
Чичваркин, Евгений Александрович
российский предприниматель
Руководство по 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
👍3
Работа с <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
👍2
<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
👍2
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
👍2
Что выведет код?
#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
👍2
👍1
Что такое 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
👍4
А вы знали, что около 15% электроэнергии в мире в 2025 году потребляют дата-центры?
Согласно отчету Международного энергетического агентства, к 2030 году потребление электроэнергии центрами обработки данных увеличится более чем вдвое и достигнет 945 ТВт·ч, что сопоставимо с годовым потреблением Японии. Основная причина роста — искусственный интеллект, на который в 2024 году уже приходилось 15% от общего энергопотребления дата-центров.
Proof
#facts
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
"Конфиденциальность — это право, а не привилегия."
Павел Дуров, основатель Telegram, сказал это в 2014 году в посте о миссии компании.
Биография
#Citation #Biography
Please open Telegram to view this post
VIEW IN TELEGRAM
Wikipedia
Дуров, Павел Валерьевич
российский предприниматель, основатель VK и Telegram
👍1
Автоупаковка и автораспаковка типов в Java
Java разделяет примитивные типы (int, boolean, char и др.) и ссылочные типы (в том числе классы-обертки Integer, Boolean, Character и т.д.). Чтобы упростить работу с обертками, Java (начиная с версии 1.5) ввела механизм автоупаковки (autoboxing) и автораспаковки (unboxing) — автоматическое преобразование между примитивами и их объектными аналогами.
Автоупаковка (Autoboxing)
Это автоматическое преобразование примитива в объект соответствующего класса-обертки.
Пример:
Java компилятор сам преобразует это в:
Автораспаковка (Unboxing)
Обратное преобразование — объект-обертка в примитив.
Пример:
На самом деле компилятор превращает это в:
Как это работает в памяти
До автоупаковки
С автоупаковкой
Примеры использования
Зачем нужна автоупаковка
Унификация с коллекциями
Удобство синтаксиса
Писать проще и чище:
Обратная совместимость
Автоупаковка позволяет использовать новые коллекции с примитивами, не ломая старый код.
Подводные камни
1. NullPointerException
Автораспаковка объекта, равного null, вызывает исключение:
2. Производительность
Автоупаковка создает лишние объекты, особенно в циклах:
Альтернатива:
3. Сравнение ссылок
А вот:
Потому что:
Integer.valueOf(...) кэширует значения от -128 до 127.
== сравнивает ссылки, а не значения.
4. Неявное создание объектов
Может вызвать нагрузку на сборщик мусора, если упакованные значения активно создаются и исчезают, особенно в многопоточной среде.
Разбор кэширования (Integer Cache)
Это реализовано внутри Integer.valueOf():
Практические советы
Используйте примитивы, если нет необходимости в объектах (например, в счетчиках, математике).
Избегайте упаковки в горячих циклах, особенно в производительном коде.
Будьте осторожны с null — автораспаковка null всегда приведет к ошибке.
Для сравнения используйте equals(), а не ==.
#Java #для_новичков #beginner #reference_types #Autoboxing #Unboxing
Java разделяет примитивные типы (int, boolean, char и др.) и ссылочные типы (в том числе классы-обертки Integer, Boolean, Character и т.д.). Чтобы упростить работу с обертками, Java (начиная с версии 1.5) ввела механизм автоупаковки (autoboxing) и автораспаковки (unboxing) — автоматическое преобразование между примитивами и их объектными аналогами.
Автоупаковка (Autoboxing)
Это автоматическое преобразование примитива в объект соответствующего класса-обертки.
Пример:
Integer x = 5; // int -> Integer автоматически
Java компилятор сам преобразует это в:
Integer x = Integer.valueOf(5);
Автораспаковка (Unboxing)
Обратное преобразование — объект-обертка в примитив.
Пример:
int y = x; // Integer -> int автоматически
На самом деле компилятор превращает это в:
int y = x.intValue();
Как это работает в памяти
До автоупаковки
int x = 10;
Integer y = new Integer(x); // вручную
x — хранится в стеке, занимает 4 байта.
y — объект в куче, содержит поле типа int со значением 10 и дополнительную информацию (например, hashCode, class pointer и т.д.).
С автоупаковкой
Integer z = 10;
Компилятор заменит это на Integer.valueOf(10), что использует кэш оберток от -128 до 127.
Примеры использования
List<Integer> numbers = new ArrayList<>();
numbers.add(10); // int -> Integer (autoboxing)
int n = numbers.get(0); // Integer -> int (unboxing)
Это работает, потому что ArrayList хранит только объекты, а int автоматически упаковывается и распаковывается.
Зачем нужна автоупаковка
Унификация с коллекциями
List<Integer> list = new ArrayList<>();
list.add(42); // без ручного создания new Integer(42)
Удобство синтаксиса
Писать проще и чище:
Integer sum = 0;
for (int i = 0; i < 10; i++) {
sum += i; // автораспаковка и автоупаковка
}
Обратная совместимость
Автоупаковка позволяет использовать новые коллекции с примитивами, не ломая старый код.
Подводные камни
1. NullPointerException
Автораспаковка объекта, равного null, вызывает исключение:
Integer x = null;
int y = x; // NullPointerException
2. Производительность
Автоупаковка создает лишние объекты, особенно в циклах:
Integer sum = 0;
for (int i = 0; i < 1000; i++) {
sum += i; // каждый шаг — распаковка, сложение, упаковка
}
Альтернатива:
int sum = 0; // быстрее и без накладных расходов
3. Сравнение ссылок
Integer a = 1000;
Integer b = 1000;
System.out.println(a == b); // false
А вот:
Integer a = 100;
Integer b = 100;
System.out.println(a == b); // true — значения из кэша
Потому что:
Integer.valueOf(...) кэширует значения от -128 до 127.
== сравнивает ссылки, а не значения.
4. Неявное создание объектов
Может вызвать нагрузку на сборщик мусора, если упакованные значения активно создаются и исчезают, особенно в многопоточной среде.
Разбор кэширования (Integer Cache)
Integer x = 127;
Integer y = 127;
System.out.println(x == y); // true
Integer x = 128;
Integer y = 128;
System.out.println(x == y); // false
Причина — кэш для Integer в диапазоне [-128; 127].
Это реализовано внутри Integer.valueOf():
public static Integer valueOf(int i) {
if (i >= -128 && i <= 127)
return IntegerCache.cache[i + 128];
else
return new Integer(i);
}
Практические советы
Используйте примитивы, если нет необходимости в объектах (например, в счетчиках, математике).
Избегайте упаковки в горячих циклах, особенно в производительном коде.
Будьте осторожны с null — автораспаковка null всегда приведет к ошибке.
Для сравнения используйте equals(), а не ==.
#Java #для_новичков #beginner #reference_types #Autoboxing #Unboxing
👍2