12073
Присоединяйтесь к нашему каналу и погрузитесь в мир для Java-разработчика Связь: @devmangx РКН: https://clck.ru/3H4WUg
IntelliJ IDEA начнет использовать JSpecify как основную null-safe библиотеку начиная с версии 2025.3.
"Переход на JSpecify это хороший пример того, как совместная работа в экосистеме Java приводит не просто к очередному стандарту, а к тому, который реально приносит пользу разработчикам."
👉 Java Portal
Мы охотились за лишними 300 мс задержки в микросервисе. Думали, что это сборщик мусора в Java.
Два дня крутили настройки JVM. Ноль эффекта.
А настоящая проблема оказалась в git clone внутри init-контейнера.
Сервис случайно настроили так, что он на каждом старте клонировал репозиторий ради одного конфиг-файла.
Клонирование было медленным, но задержка терялась на фоне общего старта приложения.
Сервис не тормозил - он просто постоянно перезапускался.
Всегда проверяйте сайдкары и init-контейнеры раньше, чем лезете в логику приложения.
👉 Java Portal
Подсказка по Java: начиная с Java 9 можно использовать Stream.takeWhile() для удобного «нарезания» списков через стримы. Это простой способ взять элементы, пока выполняется нужное условие, без лишнего кода.
List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9);
Вместо:
List<Integer> result = new ArrayList<>();
for (Integer n : numbers) {
if (n < 5) {
result.add(n);
} else {
break;
}
}
System.out.println(result); // [1, 2, 3, 4]
result = numbers.stream()
.takeWhile(n -> n < 5)
.toList();
System.out.println(result); // [1, 2, 3, 4]
Проект, который я советую каждому разработчику сделать хотя бы раз, написать свой парсер JSON, который превращает строку в нативный объект языка, например словарь.
Формат JSON настолько привычен, что мы просто пользуемся готовыми парсерами и редко задумываемся, как они устроены внутри. Вот основные шаги, если хочешь собрать такой парсер с нуля:
Разобраться со спецификацией JSON.
Написать токенайзер, который выделяет токены из строки (можно использовать Lex).
Определить грамматику JSON по спецификации с помощью Yacc.
Реализовать обработку ошибок, красивый вывод и указание позиции ошибки в строке.
Собрать нативный объект языка — словарь, hashmap и т.д.
Прогнать реализацию на тестах, чтобы убедиться в корректности.
Если хочешь усложнить задачу — не используй Lex и Yacc, а напиши токенайзер и парсер полностью вручную, специально под JSON, без универсальности.
Сделав такой проект, ты не только поймёшь, как работает JSON, но и:
почему его парсинг считается относительно медленным и затратным
как устроена стадия парсинга в любом компиляторе
насколько всё это интересно, если копнуть глубже
Этот проект реально прокачает твои навыки решения задач. Если решишься, то желаю удачи!
👉 Java Portal
Если нужно внедрить сгруппированные конфигурационные параметры в классы, можно использовать аннотацию @ConfigurationProperties вместо @Value@Value обычно применяют для внедрения отдельных свойств:
@Value("${app.name}")
private String appName;
@ConfigurationProperties лучше подходит для более сложных, сгруппированных настроек:email:
host: smtp.example.com
port: 587
username: user@example.com
password: secret
@Component
@ConfigurationProperties(prefix = "email")
public class EmailProperties {
private String host;
private int port;
private String username;
private String password;
// геттеры и сеттеры
}
@Service
public class EmailService {
private final EmailProperties emailProperties;
public EmailService(EmailProperties emailProperties) {
this.emailProperties = emailProperties;
}
}
👩💻 Ищем Java разработчиков. Удалёнка, релокейт платим много!
Специально для Вас, собираем лучшие вакансии для Java разработчиков с прямыми контактами в Telegram на канале @it_match_java
Подпишись чтобы не упустить свой шанс получить лучший оффер!
➡️ Посмотреть вакансии
Spring Boot 4 + Jackson 3 сделали клиентскую фильтрацию через @JsonView гораздо аккуратнее и удобнее
Раньше приходилось оборачивать объекты в MappingJacksonValue 😫
Теперь всё проще — просто используй .hint()
👉 Java Portal
Совет по Java: в циклах лучше использовать StringBuilder, а не String для конкатенации строк.
String - неизменяемый объект, из-за чего при каждой конкатенации создаётся новая строка. Это сильно бьёт по производительности, особенно в больших циклах.
StringBuilder - изменяемый, заточен под многократное добавление строк и работает куда быстрее.
// Неэффективный способ:
String result = "";
for (int i = 0; i < 1000; i++) {
result += i; // при каждой итерации создаётся новый объект String
}
// Более эффективный способ:
StringBuilder result = new StringBuilder();
for (int i = 0; i < 1000; i++) {
result.append(i); // добавление в тот же буфер, без лишних аллокаций
}
kill -15 даёт ядру возможность завершить процесс аккуратно, чтобы тот успел всё почистить и закрыть как положено.
kill -9 — это уже жёсткий килл, без шансов на «прощальную речь». Процесс просто вырубается, не успев освободить ресурсы или записать данные.
Вот пример с node http-server: при обычном завершении (-15) он корректно закрывает соединения, а при -9 просто падает без возможности что-то доработать.
Короче, будь готов к -9, но надейся на -15.
👉 Java PortalМ
Spring Framework 7 добавил встроенный механизм ретраев. Больше не нужно подключать внешнюю зависимость spring-retry. Если надо больше контроля, чем даёт @Retryable, используй RetryTemplate
👉 Java Portal
Учебник по Java от Андрея Иванцова теперь доступен онлайн на GitBook. В нём собрано всё, что нужно новичку: от простых типов данных и строк до исключений и коллекций. Материал подан по делу, с примерами кода и понятными объяснениями.
Ссылка для тех, кто хочет прокачаться: andrey-ivantsov.gitbook.io/java
👉 Java Portal
Совет по Docker
Как понять, что раздувает образ
Любой Docker-образ состоит из слоев.
Каждая строка в Dockerfile добавляет новый слой.
По этим слоям можно понять, почему образ получается большим, долго собирается или плохо кешируется.
Вот как посмотреть слои и узнать, что именно менялось в каждом из них.
Используй утилиту dive.
Она показывает наглядно:
- какие слои созданы
- какие файлы добавлены или изменены
- сколько места занимает каждый слой
Когда начинаешь изучать слои образа, можно быстро выяснить:
• какая команда в Dockerfile добавляет лишний вес
• как оптимизировать сборку, чтобы образ был меньше и собирался быстрее
Dive также дает оценку «эффективности» образа. Она показывает, насколько много данных дублируется или просто впустую занимает место в слоях.
👉 Java Portal
Не все данные обрабатываются одинаково. Понимание, когда подходит batch, а когда stream, решает, получится ли у тебя нормальная архитектура или скрытый тормоз внутри.
Batch Processing собирает данные и обрабатывает их пачками.
Подходит, когда нет требований к моментальной реакции: ежедневные отчеты, бухзакрытия, историческая аналитика.
Он проще, нормально тянет большие объемы и дешевле по деньгам,
но появляется задержка. Событие уже случилось, а ты обрабатываешь его потом.
Stream Processing работает с данными прямо в потоке.
Отлично для мониторинга, антифрода, рекомендаций в реальном времени.
Скорость выше, но инфраструктура сложнее и поддержка дороже.
Часто косячат: ставят stream там, где батча за глаза, или наоборот, лепят batch туда, где важна минимальная задержка.
Фишка не в том, чтобы выбрать самое модное, а в том, чтобы попасть в реальный ритм бизнеса и решить конкретную задачу.
А если ресурсы сильно ограничены, скорее всего, batch уже закрывает потребности.
👉 Java Portal
Недавно в регионе US-EAST-1 у AWS были сбои.
Как бы ты спроектировал деплой микросервиса и инфраструктуру вокруг, чтобы пережить падение одной инстансы, сбой базы данных или даже отказ целого дата-центра ?
Исправляем ту самую ошибку на миллиарды долларов? 👀
Улучшения поддержки null-безопасности в Spring Boot 4 могут оказаться самым недооцененным нововведением предстоящего релиза.
Аннотации NonNull и Nullable теперь полноценные граждане во всем фреймворке. Spring постепенно переводит весь код на единый и последовательный подход.
Хватит гадать, вернет ли сервис null. IDE поймает потенциальный NPE уже на этапе компиляции, а не в рантайме.
То ли поправка, о которой мечтал Тони Хоар? Не полностью. Но это важный шаг к более безопасному Java-коду.
Самое приятное? Не нужно мигрировать за один заход. Можно двигаться постепенно, делая код надежнее и уверенно продвигаясь вперед.
Null-безопасность в Spring Boot 4 даст нам ту же уверенность в кодовой базе, что и тесты. 👍
👉 Java Portal
Каким будет результат?
👉 Java Portal
Парень собрал репозиторий, чтобы показать новые встроенные возможности отказоустойчивости в Spring Framework 7. Никаких дополнительных зависимостей вроде spring-retry — все уже под капотом 🤯
Можно использовать декларативную аннотацию Retry, чтобы настроить, как и когда нужно повторять выполнение
Можно написать свой listener, чтобы получить наблюдаемость за разными событиями.
Нужен больше контроля — бери RetryTemplate
Хочешь ограничить число одновременных подключений — используй Concurrent
👉 Java Portal
Большинство разработчиков пользуются всего парой Git команд.
Вот еще 15, которые сэкономят вам кучу времени.
git stash → Сохранить работу без коммита. Можно прыгать по веткам, не теряя правки.
git reflog → Находит потерянные коммиты. Спасательный круг, если что-то пошло не так с git reset.
git bisect → Двоичный поиск по коммитам, чтобы вычислить баг. Гораздо быстрее ручной проверки.
git rebase -i → Причесывает историю перед пушем. Сквош, перестановка или правка коммитов.
git cherry-pick → Применяет нужные коммиты в другую ветку. Без полноценного merge.
git diff --staged → Показывает, что именно пойдет в коммит. Помогает поймать косяки заранее.
git commit --amend → Поправить последний коммит или добавить забытые файлы.
git reset HEAD~1 → Откатывает последний коммит, но оставляет изменения. Начинаешь заново, ничего не теряя.
git clean -fd → Удаляет все неотслеживаемые файлы и папки. Полная очистка, когда нужно начать на чистую.
git log --oneline --graph → Компактная визуализация истории. Ветки и слияния видно как на ладони.
git blame → Показывает, кто и когда писал каждую строку. Удобно искать момент появления бага.
git show → Детальная инфа по любому коммиту. И изменения, и метаданные.
git remote -v → Список всех удаленных репозиториев. Полезно, чтобы проверить, куда вы пушите.
git fetch --prune → Обновляет информацию о ремоутах и удаляет устаревшие ветки.
git diff branch1..branch2 → Сравнивает две ветки. Видно, что именно в них различается.
Разбор логов при запуске Spring Boot
Когда запускаешь Spring Boot и в консоли пролетают тонны логов - вот что это всё значит:
1. Spring Boot Banner
Сначала появляется ASCII-баннер с версией Spring Boot:
:: Spring Boot :: (v3.3.4)
Он показывает версию приложения и данные JVM.
2. Стартовая информация
Пример строки:
Starting DemoApplication using Java 21 on LAPTOP with PID 4523
Отображает главный класс, версию Java и PID процесса.
3. Активные профили
Если видишь:
The following profiles are active: dev
Значит, загружается application-dev.yml — удобно для конфигов под разные окружения.
4. Инициализация ApplicationContext
Spring создаёт ApplicationContext, сканирует компоненты, конфигурации и автоконфигурации.
Пример лога:
Refreshing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext
5. Фаза автоконфигурации
Spring Boot подхватывает AutoConfiguration-классы и автоматически связывает бины.
Пример:
Tomcat initialized with port(s): 8080 (http)
Хочешь увидеть детали — запускай с флагом --debug или --trace.
6. Создание и инициализация бинов
Типичный лог:
Initializing Spring DispatcherServlet 'dispatcherServlet'
Это значит, что веб-слой готов принимать запросы.
7. Запуск веб-сервера
В зависимости от стека:
- Tomcat — для Spring MVC
- Netty — для WebFlux
Пример:
Tomcat started on port(s): 8080 (http) with context path ''
8. Метрики старта
Spring Boot 3.x добавил StartupStep-метрики, чтобы отслеживать, на что уходит время при старте (видно, если включён Actuator).
9. Приложение готово
Финальный лог:
Started DemoApplication in 2.345 seconds (JVM running for 2.789)
Контекст полностью загружен, приложение работает.
Как посмотреть всё в реальном времени
Запусти приложение с флагом --debug:
java -jar app.jar --debug
Ты получишь детализированный отчёт об автоконфигурации и последовательности запуска — удобно для отладки и понимания, что реально происходит при старте.
👉 Java Portal
Spring Boot: можно использовать @SpringBootApplication(exclude = …), чтобы отключить определённые классы автоконфигурации.
✅ Один из возможных поводов сделать это когда у тебя есть своя конфигурация, которая конфликтует со стандартной.
👉 Java Portal
Камень/ножницы/бумага, реализовано на Java25 в http://Game.java
void main() {
IO.println("rock/paper/scissors:");
var u = IO.readln(); // читаем ввод пользователя
if (u.equals("exit")) return; // выходим, если введено "exit"
var c = "rock,paper,scissors".split(","); // список вариантов
var i = List.of(c).indexOf(u); // индекс выбранного пользователем варианта
if (i < 0) return; // если введено что-то не из списка — выходим
var j = new Random().nextInt(3); // случайный выбор компьютера
IO.println("Computer: " + c[j]);
IO.println(i == j ? "Tie!" : (i == (j + 1) % 3 ? "You win!" : "Computer wins!"));
}
То, что доктор прописал!
9 самых необходимых IT-каналов, которые должен читать каждый айтишник:
Доктор Mobile - лечим ваш смартфон, минимум слов, максимум пользы.
Доктор Python — коды, хаки и фичи.
Доктор Techlogy — свежие технологии и их применение.
Доктор Cyber — информационная безопасность без скуки.
Доктор GitHub — лучшие репозитории от врача.
Доктор IT — всё о цифровом мире и его инсайтах.
Доктор GameDev — рецепты создания игр и гайды.
Доктор GPT — лучшие промпты и сервисы ИИ.
Доктор Memes — смех лечит лучше любых апдейтов.
Доктор C++ — фичи, советы и код без боли.
Подпишись, чтобы стать профессором, а не пациентом.
Дерево зависимостей Spring Boot 4, где в деле видно Jackson 3
Обрати внимание на новые пакеты tools.jackson.* (ядро Jackson 3), идущие вместе с com.fasterxml.jackson.annotations:2.20. Это не ошибка — Jackson 3 специально использует те же аннотации, что и в версии 2, ради совместимости
👉 Java Portal
Spring Boot 4 делает настройку HTTP-интерфейсов гораздо чище
Больше никакого ручного создания прокси и шаблонного кода. Просто используй @ImportHttpServices и готово.
Было 5+ строк конфигурации на каждый клиент → стала одна аннотация
👉 Java Portal
Совет по Spring Boot 4. В Jackson 3 теперь в приоритете JsonMapper для работы с JSON. Обрати внимание на новый import. ObjectMapper из com.fasterxml больше не нужен. JsonMapper теперь основной инструмент для JSON в современных Spring-приложениях.
👉 Java Portal
Java/Backend. Интервью. Сценарный вопрос про распределенный лок:
У тебя есть критичный сервис, допустим обработка заказов, который крутится на нескольких инстансах в Kubernetes. Чтобы избежать гонки, когда два инстанса одновременно берут один и тот же заказ, ты ставишь распределенный лок через Redis setnx с TTL 10 секунд.
Какой критичный кейс все равно возможен, если один из инстансов словит Full GC паузу длиной 15 секунд сразу после получения лока? Опиши ситуацию split-brain и к чему она приведет по данным.
Как это разруливать на интервью:
→ сначала важно отметить, что простой Redis-лок с TTL помогает, если сервис просто упал, но создает новую, куда более опасную проблему
→ баг в том, что длинная пауза, например Full GC, может быть дольше, чем TTL лока
→ и вот что ломается (Split-Brain):
Service A берет лок,
и тут же уходит в GC на 15 секунд
Через 10 секунд Redis удаляет лок по TTL
Service B спокойно берет тот же лок,
и начинает обрабатывать заказ
Через 15 секунд Service A просыпается
все еще уверенный, что лок у него
и тоже обрабатывает этот же заказ
→ итог: два сервиса одновременно трогают один и тот же заказ. Данные ломаются. Например клиенту списывают деньги дважды.
→ реальное решение (меняем дизайн): вообще избавиться от лока
Кладем заказы в очередь сообщений,
например Kafka или RabbitMQ
Consumer group с несколькими инстансами читает этот топик
Брокер гарантирует, что каждое сообщение (заказ) уходит только одному инстансу из группы
👉 Java Portal
Совет по Java: начиная с Java 8 можно легко убирать null значения с помощью list.removeIf(Objects::isNull)
👉 Java Portal
Видишь разницу между этими двумя кусками кода? 👀
На первый взгляд делают одно и то же, но…
В первом варианте все классы вынуждены реализовывать методы, которые им вообще не нужны.
Во втором интерфейсы разделены: каждый класс берет только то, что реально использует.
Принцип разделения интерфейсов (ISP)
👉 Java Portal
Подсказка по Spring Boot 4: коллекции с nullable-элементами (List<Nullable String>) помогают ловить NullPointerException на этапе компиляции вместо рантайма. Больше никаких сюрпризов при обработке API-ответов, где могут прилетать null.
👉 Java Portal
Spring Boot совет: если хочешь, чтобы DTO спокойно переживали лишние поля в JSON от клиента и не роняли API, добавляй аннотацию @JsonIgnoreProperties(ignoreUnknown = true)
Jackson тогда просто проигнорит поля, которых нет в твоем классе, вместо того чтобы кидать UnrecognizedPropertyException. Удобно, когда фронты любят прислать что-нибудь от себя.
Допустим, есть DTO:
public class UserDTO {
private String name;
private int age;
// getters/setters
}{
"name": "Alice",
"age": 25,
"extraField": "not expected"
}UnrecognizedPropertyException: Unrecognized field "extraField"
@JsonIgnoreProperties@JsonIgnoreProperties(ignoreUnknown = true)
public class UserDTO {
private String name;
private int age;
// getters/setters
}