Собираем сортировку задач по зависимостям!
Нужно получить порядок выполнения задач, где одна задача может зависеть от другой. Например, сначала build, потом test, а deploy только после test.
В этой задаче:
Такой подход полезен для пайплайнов, сборки модулей, миграций, очередей обработки и любых сценариев, где порядок нельзя задавать руками.
👉 Java Ready | #задача
Нужно получить порядок выполнения задач, где одна задача может зависеть от другой. Например, сначала build, потом test, а deploy только после test.
В этой задаче:
• описываем граф зависимостей
• считаем входящие связи
• кладём свободные задачи в очередь
Такой подход полезен для пайплайнов, сборки модулей, миграций, очередей обработки и любых сценариев, где порядок нельзя задавать руками.
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4👍1🔥1
Почему Collections.unmodifiableList не делает настоящую копию?
В Java часто нужно отдать список наружу так, чтобы вызывающий код не мог его изменить. Например, из getter-метода, DTO, настроек или внутреннего состояния сервиса.
Для этого часто используют Collections.unmodifiableList.
Через view действительно нельзя вызвать add или remove. Такой вызов закончится исключением.
Но важный нюанс в том, что unmodifiableList создаёт не копию, а представление поверх исходного списка.
Если изменить оригинальный список, изменения будут видны и через view.
На экране появится новое значение, хотя сам view вроде бы неизменяемый. Он просто запрещает менять список через себя, но не защищает от изменений оригинала.
Из-за этого легко получить странный баг. Метод вернул наружу список ролей, потом внутренний код сервиса поменял исходную коллекцию, а внешний код внезапно увидел другое состояние.
Если нужна именно независимая копия, лучше использовать List.copyOf.
Теперь snapshot не связан с дальнейшими изменениями исходного списка. Это уже снимок состояния на момент создания.
Разница особенно заметна в классах с внутренним состоянием.
Так вызывающий код получает безопасный результат и не может случайно повлиять на объект изнутри.
Если элементы списка сами изменяемые, копия списка не делает глубокую копию элементов. Например, список объектов UserRole всё ещё будет содержать те же самые объекты.
Поэтому для настоящей неизменяемости важно думать не только о коллекции, но и о типах внутри неё. Для строк, чисел, enum и record-объектов такой подход обычно работает хорошо.
Плохой вариант выглядит так.
Если внешний код сохранит ссылку на исходный список, он сможет поменять состояние объекта уже после создания.
Безопаснее делать defensive copy прямо в конструкторе.
Тогда объект получает своё стабильное состояние. Даже если исходный список потом очистят или дополнят, поле внутри User не изменится.
👉 Java Ready | #совет
В Java часто нужно отдать список наружу так, чтобы вызывающий код не мог его изменить. Например, из getter-метода, DTO, настроек или внутреннего состояния сервиса.
Для этого часто используют Collections.unmodifiableList.
List<String> roles = new ArrayList<>();
List<String> view = Collections.unmodifiableList(roles);
Через view действительно нельзя вызвать add или remove. Такой вызов закончится исключением.
Но важный нюанс в том, что unmodifiableList создаёт не копию, а представление поверх исходного списка.
Если изменить оригинальный список, изменения будут видны и через view.
roles.add("admin");
System.out.println(view);На экране появится новое значение, хотя сам view вроде бы неизменяемый. Он просто запрещает менять список через себя, но не защищает от изменений оригинала.
Из-за этого легко получить странный баг. Метод вернул наружу список ролей, потом внутренний код сервиса поменял исходную коллекцию, а внешний код внезапно увидел другое состояние.
Если нужна именно независимая копия, лучше использовать List.copyOf.
List<String> snapshot = List.copyOf(roles);
Теперь snapshot не связан с дальнейшими изменениями исходного списка. Это уже снимок состояния на момент создания.
Разница особенно заметна в классах с внутренним состоянием.
class User {
private final List<String> roles = new ArrayList<>();
List<String> roles() {
return List.copyOf(roles);
}
}Так вызывающий код получает безопасный результат и не может случайно повлиять на объект изнутри.
Если элементы списка сами изменяемые, копия списка не делает глубокую копию элементов. Например, список объектов UserRole всё ещё будет содержать те же самые объекты.
Поэтому для настоящей неизменяемости важно думать не только о коллекции, но и о типах внутри неё. Для строк, чисел, enum и record-объектов такой подход обычно работает хорошо.
Плохой вариант выглядит так.
class User {
private final List<String> roles;
User(List<String> roles) {
this.roles = roles;
}
}Если внешний код сохранит ссылку на исходный список, он сможет поменять состояние объекта уже после создания.
Безопаснее делать defensive copy прямо в конструкторе.
this.roles = List.copyOf(roles);
Тогда объект получает своё стабильное состояние. Даже если исходный список потом очистят или дополнят, поле внутри User не изменится.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤9🔥7👍5
Шпаргалка по устройству JVM!
Например, Heap хранит объекты и делится на young/old generation, а Stack содержит фреймы вызовов, локальные переменные и работает отдельно для каждого потока.
На картинке основные области памяти JVM: Heap, Stack, Metaspace, PC Register и Native Method Stack, а также краткая логика работы GC и сравнение популярных сборщиков мусора.
Сохрани, чтобы не потерять!
👉 Java Ready | #ресурс
Например, Heap хранит объекты и делится на young/old generation, а Stack содержит фреймы вызовов, локальные переменные и работает отдельно для каждого потока.
На картинке основные области памяти JVM: Heap, Stack, Metaspace, PC Register и Native Method Stack, а также краткая логика работы GC и сравнение популярных сборщиков мусора.
Сохрани, чтобы не потерять!
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12❤6🔥6
Как в Java чище проверять тип через pattern matching?
Раньше при проверке типа часто писали так:
Код рабочий, но в нём есть лишнее приведение типа. Сначала Java уже проверила, что value это String, а потом мы всё равно руками делаем cast.
В современном Java можно записать короче:
Переменная text доступна только там, где проверка точно прошла.
Это удобно для валидации:
И для обработки разных входных объектов:
При этом Java не даст использовать переменную вне безопасной области:
Здесь text уже доступен после return, потому что дальше код дойдёт только если value действительно String.
Такой синтаксис особенно приятен в коде с Object, событиями, DTO, sealed-иерархиями и обработкой внешних данных.
👉 Java Ready | #совет
Раньше при проверке типа часто писали так:
if (value instanceof String) {
String text = (String) value;
System.out.println(text.length());
}Код рабочий, но в нём есть лишнее приведение типа. Сначала Java уже проверила, что value это String, а потом мы всё равно руками делаем cast.
В современном Java можно записать короче:
if (value instanceof String text) {
System.out.println(text.length());
}Переменная text доступна только там, где проверка точно прошла.
Это удобно для валидации:
if (input instanceof String text && !text.isBlank()) {
return text.trim();
}И для обработки разных входных объектов:
if (event instanceof LoginEvent login) {
audit(login.userId());
}При этом Java не даст использовать переменную вне безопасной области:
if (!(value instanceof String text)) {
return;
}
System.out.println(text.length());Здесь text уже доступен после return, потому что дальше код дойдёт только если value действительно String.
Такой синтаксис особенно приятен в коде с Object, событиями, DTO, sealed-иерархиями и обработкой внешних данных.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥9👍6❤5
Media is too big
VIEW IN TELEGRAM
Tutorialspoint Java Tutorial - большой справочник по Java!
На сайте собраны разделы по синтаксису, типам данных, операторам, циклам, массивам, ООП, исключениям, коллекциям, потокам, файлам и другим темам, которые часто нужны при изучении и повторении языка.
Оставляю ссылочку на Tutorialspoint
👉 Java Ready | #ресурс
На сайте собраны разделы по синтаксису, типам данных, операторам, циклам, массивам, ООП, исключениям, коллекциям, потокам, файлам и другим темам, которые часто нужны при изучении и повторении языка.
Оставляю ссылочку на Tutorialspoint
Please open Telegram to view this post
VIEW IN TELEGRAM
❤13👍5🔥5
Хорошая статья про JWT-авторизацию на Spring Security!
Автор показывает, как собрать авторизацию через access tokens и связать Spring Security с регистрацией, логином, ролями и проверкой токена в защищённых запросах.
В статье автор показывает:
• как настроить регистрацию и вход пользователя
• как выпускать и проверять JWT-токен
• как подключить фильтр авторизации к SecurityFilterChain
👉 Java Ready | #статья
Автор показывает, как собрать авторизацию через access tokens и связать Spring Security с регистрацией, логином, ролями и проверкой токена в защищённых запросах.
В статье автор показывает:
• как настроить регистрацию и вход пользователя
• как выпускать и проверять JWT-токен
• как подключить фильтр авторизации к SecurityFilterChain
Продолжай читать на Habr
Please open Telegram to view this post
VIEW IN TELEGRAM
❤9👍5🔥4
Собираем простой шаблонизатор строк на Java!
Нужно заменить плейсхолдеры вида {name} и {orderId} значениями из Map. Если значение отсутствует, оставим плейсхолдер как есть, чтобы ошибка была заметна в итоговом тексте.
В этой задаче:
Такой шаблонизатор полезен для писем, логов, уведомлений, CLI-сообщений и генерации простых текстов без подключения тяжёлого template engine.
👉 Java Ready | #задача
Нужно заменить плейсхолдеры вида {name} и {orderId} значениями из Map. Если значение отсутствует, оставим плейсхолдер как есть, чтобы ошибка была заметна в итоговом тексте.
В этой задаче:
• находим плейсхолдеры через Pattern
• достаём имя переменной из группы
• безопасно подставляем значение
Такой шаблонизатор полезен для писем, логов, уведомлений, CLI-сообщений и генерации простых текстов без подключения тяжёлого template engine.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9❤3🔥3
Разбираем CompletableFuture: 7 приёмов для асинхронного Java-кода!
CompletableFuture помогает строить цепочки асинхронных операций без ручного управления Thread. С ним удобно запускать фоновые задачи, преобразовывать результаты, объединять независимые запросы, обрабатывать ошибки и ограничивать время ожидания.
👉 Java Ready | #шпора
CompletableFuture помогает строить цепочки асинхронных операций без ручного управления Thread. С ним удобно запускать фоновые задачи, преобразовывать результаты, объединять независимые запросы, обрабатывать ошибки и ограничивать время ожидания.
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11❤3👍3🤝2
Полезный разбор Java-приложений в Kubernetes!
Автор собирает практики, которые помогают запускать JVM-сервисы в контейнерах предсказуемо и без лишних проблем с ресурсами, healthcheck и завершением процесса.
В статье автор показывает:
• как учитывать память контейнера при настройке JVM
• зачем нужны readiness и liveness probes
• почему graceful shutdown важен для сервисов под нагрузкой
👉 Java Ready | #статья
Автор собирает практики, которые помогают запускать JVM-сервисы в контейнерах предсказуемо и без лишних проблем с ресурсами, healthcheck и завершением процесса.
В статье автор показывает:
• как учитывать память контейнера при настройке JVM
• зачем нужны readiness и liveness probes
• почему graceful shutdown важен для сервисов под нагрузкой
Продолжай читать на Habr
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5👍3🔥2