Совет по Java: возвращайте Collections.emptyList(), List.of() или Set.of() вместо null, чтобы не плодить проверки на null в вызывающем коде.
👉 Java Portal
// ❌ Нужен null-check:
public List<String> findUsers() {
if (!dataAvailable()) {
return null; // заставляет вызывающий код проверять на null
}
return loadUsers();
}
List<String> users = findUsers();
if (users != null) {
users.forEach(System.out::println);
}
// ✅ Без null-check:
public List<String> findUsers() {
if (!dataAvailable()) {
return Collections.emptyList(); // или List.of()
}
return loadUsers();
}
// Вызывающая сторона:
List<String> users = findUsers();
users.forEach(System.out::println); // проверка на null не нужна
Please open Telegram to view this post
VIEW IN TELEGRAM
❤8👍5
Вышел релиз IntelliJ IDEA 2025.3!
В этой версии завезли несколько заметных обновлений – все они подробно описаны и показаны в демках на странице “Что нового”.
Зацени
👉 Java Portal
В этой версии завезли несколько заметных обновлений – все они подробно описаны и показаны в демках на странице “Что нового”.
Зацени
Please open Telegram to view this post
VIEW IN TELEGRAM
1🔥6
Java-совет: когда нужно наполнять значения в Map, например списки, удобно использовать computeIfAbsent().
Классический способ:
С использованием computeIfAbsent:
👉 Java Portal
Классический способ:
Map<String, List<String>> map = new HashMap<>();
if (!map.containsKey("key")) {
map.put("key", new ArrayList<>());
}
map.get("key").add("listValue");
С использованием computeIfAbsent:
map.computeIfAbsent("key", k -> new ArrayList<>())
.add("listValue");Please open Telegram to view this post
VIEW IN TELEGRAM
👍17
Твой Dockerfile не "простой". Он просто недописан.
Большинство девов за всю жизнь используют всего 5 инструкций Dockerfile:
FROM, COPY, RUN, EXPOSE, CMD, ну и иногда ENV, если уж прям заморочились.😱
Вот почему твоя команда Ops и пользователи молча тебя ненавидят.
Вот несколько инструкций, про которые ты, скорее всего, не знаешь:
- HEALTHCHECK: контейнер не становится здоровым только потому, что он запущен.
Нет, Kubernetes сам не поймет, что приложение внутри уже сдохло.
Скажи ему, как это проверять. Или дай Ops’ам удовольствие дебажить цикл перезапусков контейнеров в проде.
- SHELL:
По умолчанию это /bin/sh -c. Хочешь другое, используй SHELL.
Меньше экранирования, меньше проблем с кроссплатформой.
- STOPSIGNAL: не оставляй приложение подвисшим.
Задает сигнал, который Docker отправляет при остановке контейнера.
Используй тот сигнал, который твое приложение реально обрабатывает.
Больше никаких зомби-контейнеров и сломанной "корректной остановки".
- ONBUILD
Хочешь сделать базовые образы умнее, используй это.
Хочешь развалить чужой пайплайн, используй неправильно.
- ARG vs ENV: перестань путать "во время сборки образа" и “во время запуска контейнера”,
ARG: существует только во время сборки
ENV: остается в финальном образе
Если ты не понимаешь разницу, не удивляйся, когда приложение ведет себя по-разному на dev и в prod.
- LABEL: метаданные не опциональны.
Это не для красоты. Это нужно инструментам, CI и аудиторам. Потом сам себе спасибо скажешь.
Dockerfile это не шелл-скрипт.
Это продовый код.
Он описывает систему, которую ты поставляешь.
Ты же не выкатываешь наполовину сделанное API, так перестань выкатывать наполовину сделанные образы.
Научись писать Dockerfile, который не отстой.💩
👉 Java Portal
Большинство девов за всю жизнь используют всего 5 инструкций Dockerfile:
FROM, COPY, RUN, EXPOSE, CMD, ну и иногда ENV, если уж прям заморочились.
Вот почему твоя команда Ops и пользователи молча тебя ненавидят.
Вот несколько инструкций, про которые ты, скорее всего, не знаешь:
- HEALTHCHECK: контейнер не становится здоровым только потому, что он запущен.
Нет, Kubernetes сам не поймет, что приложение внутри уже сдохло.
Скажи ему, как это проверять. Или дай Ops’ам удовольствие дебажить цикл перезапусков контейнеров в проде.
- SHELL:
По умолчанию это /bin/sh -c. Хочешь другое, используй SHELL.
Меньше экранирования, меньше проблем с кроссплатформой.
- STOPSIGNAL: не оставляй приложение подвисшим.
Задает сигнал, который Docker отправляет при остановке контейнера.
Используй тот сигнал, который твое приложение реально обрабатывает.
Больше никаких зомби-контейнеров и сломанной "корректной остановки".
- ONBUILD
Хочешь сделать базовые образы умнее, используй это.
Хочешь развалить чужой пайплайн, используй неправильно.
- ARG vs ENV: перестань путать "во время сборки образа" и “во время запуска контейнера”,
ARG: существует только во время сборки
ENV: остается в финальном образе
Если ты не понимаешь разницу, не удивляйся, когда приложение ведет себя по-разному на dev и в prod.
- LABEL: метаданные не опциональны.
Это не для красоты. Это нужно инструментам, CI и аудиторам. Потом сам себе спасибо скажешь.
Dockerfile это не шелл-скрипт.
Это продовый код.
Он описывает систему, которую ты поставляешь.
Ты же не выкатываешь наполовину сделанное API, так перестань выкатывать наполовину сделанные образы.
Научись писать Dockerfile, который не отстой.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6❤1😁1
Java tip: используй Files.walk(), чтобы рекурсивно пройтись по файлам в каталоге.
👉 Java Portal
public static void main(String[] args) {
Path startPath = Paths.get("src");
try (Stream<Path> paths = Files.walk(startPath)) {
paths
.filter(Files::isRegularFile)
.filter(path -> path.toString().endsWith(".java"))
.forEach(System.out::println);
} catch (IOException e) {
e.printStackTrace();
}
}Please open Telegram to view this post
VIEW IN TELEGRAM
👍14❤3
Больше десяти лет
Прямолинейный. Синхронный. Простой.
С выходом Spring Framework 6 и Spring Boot 3 пришла современная замена:
- RestClient
❓ Чем обычно характеризуется
- API на методах (getForObject, postForEntity и т.д.)
- Очень явные вызовы под каждую HTTP-операцию
- Мало “цепочек”: часто один вызов укладывается в одну строку
- Настройки раскиданы по разным местам (interceptors, error handlers, converters)
- Синтаксис исторически нарастал кусками годами
Типичный пример:
Работает, но когда запрос усложняется (headers, auth, ошибки, таймауты), читаемость начинает страдать.
❓ RestClient меняет подход к API
- Флюентный, декларативный синтаксис
- Четкое разделение между сборкой request и чтением response
- Лучше читается, когда есть headers, params, auth и т.п.
- Единый, консистентный API для всех HTTP-методов
- Централизованный builder для общей конфигурации
Типичный пример:
Это та же идея, что у RestTemplate, но API яснее, расширяемее и проще поддерживать.
❓ Зачем RestClient, если уже есть WebClient
WebClient реактивный и неблокирующий (под другую задачу)
RestClient работает как RestTemplate: обычный (не реактивный) и с ожиданием ответа, просто это его современная замена.
Многим нужен современный API, но без перехода на реактивный стек.
Spring не пытается всех загнать в WebFlux. Он просто обновил классический HTTP-клиент.
Нет, он не умер, просто его только поддерживают: багфиксы и совместимость, без новых фич.
То есть новых возможностей не будет. Только апдейты совместимости.
А развитие будет происходить в RestClient.
Причем RestClient можно создать на базе RestTemplate:
❓ Что использовать сегодня:
Используй RestTemplate, если:
- приложение легаси
- миграция слишком дорогая
- завязан на библиотеки, которые работают только с RestTemplate
Используй RestClient, если:
- ты на Boot 3 / Spring 6+
- хочешь современный и чистый API
- хочешь остаться в императивном стиле
- не хочешь или не можешь использовать WebFlux
RestTemplate это классика, почти любой Java-разработчик на Spring хотя бы раз с ним сталкивался.
Но RestClient задает точку старта для нового.
Это не про реактивность и не про переделку архитектуры.
Это просто современный HTTP-клиент, который делает код понятнее и проще в сопровождении.
Похоже на подход многих других модулей Spring, где builder упрощает создание объектов и использование классов.
И в мире, где сервисы постоянно дергают внешние API, хороший HTTP-клиент реально важен.
👉 Java Portal
RestTemplate был главным вариантом для HTTP-запросов в Spring.Прямолинейный. Синхронный. Простой.
Он больше не развивается: новых фич и улучшений не будет, плюс есть ограничения по ошибкам и расширяемости.
С выходом Spring Framework 6 и Spring Boot 3 пришла современная замена:
RestTemplate- API на методах (getForObject, postForEntity и т.д.)
- Очень явные вызовы под каждую HTTP-операцию
- Мало “цепочек”: часто один вызов укладывается в одну строку
- Настройки раскиданы по разным местам (interceptors, error handlers, converters)
- Синтаксис исторически нарастал кусками годами
Типичный пример:
RestTemplate rest = new RestTemplate();
ResponseEntity<User> response =
rest.exchange(url, HttpMethod.GET, request, User.class);
Работает, но когда запрос усложняется (headers, auth, ошибки, таймауты), читаемость начинает страдать.
- Флюентный, декларативный синтаксис
- Четкое разделение между сборкой request и чтением response
- Лучше читается, когда есть headers, params, auth и т.п.
- Единый, консистентный API для всех HTTP-методов
- Централизованный builder для общей конфигурации
Типичный пример:
User user = client.get()
.uri(url)
.header("Authorization", token)
.retrieve()
.body(User.class);
Это та же идея, что у RestTemplate, но API яснее, расширяемее и проще поддерживать.
WebClient реактивный и неблокирующий (под другую задачу)
RestClient работает как RestTemplate: обычный (не реактивный) и с ожиданием ответа, просто это его современная замена.
Многим нужен современный API, но без перехода на реактивный стек.
Spring не пытается всех загнать в WebFlux. Он просто обновил классический HTTP-клиент.
❓ RestTemplate “мертв”
Нет, он не умер, просто его только поддерживают: багфиксы и совместимость, без новых фич.
То есть новых возможностей не будет. Только апдейты совместимости.
А развитие будет происходить в RestClient.
Причем RestClient можно создать на базе RestTemplate:
RestTemplate oldRestTemplate;
var restClient = RestClient.create(oldRestTemplate);
Используй RestTemplate, если:
- приложение легаси
- миграция слишком дорогая
- завязан на библиотеки, которые работают только с RestTemplate
Используй RestClient, если:
- ты на Boot 3 / Spring 6+
- хочешь современный и чистый API
- хочешь остаться в императивном стиле
- не хочешь или не можешь использовать WebFlux
RestTemplate это классика, почти любой Java-разработчик на Spring хотя бы раз с ним сталкивался.
Но RestClient задает точку старта для нового.
Это не про реактивность и не про переделку архитектуры.
Это просто современный HTTP-клиент, который делает код понятнее и проще в сопровождении.
Похоже на подход многих других модулей Spring, где builder упрощает создание объектов и использование классов.
И в мире, где сервисы постоянно дергают внешние API, хороший HTTP-клиент реально важен.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤11👍6😁1
Java tip : можно использовать List.of() и Set.of(), чтобы создавать неизменяемые (immutable) коллекции.
Это быстрый способ получить немодифицируемые списки и множества без Collections.unmodifiableList().
Пример:
❌
👉 Java Portal
Это быстрый способ получить немодифицируемые списки и множества без Collections.unmodifiableList().
Пример:
List<String> letters = List.of("A", "B", "C");letters.add("D"); // исключение во время выполненияPlease open Telegram to view this post
VIEW IN TELEGRAM
🤯7👍6👀3
Представь, что тебя связали, кинули в багажник и увезли в ангар за городом
Похититель наклоняется к твоему уху и шепчет: "Или ты правильно отвечаешь на 3 вопроса, или пуля летит тебе прямиком в висок:
💚 Почему @Transactional в Spring не работает, если вызвать метод внутри того же класса?
💚 Почему Kafka с exactly-once семантикой в 3 раза медленнее обычной и когда можно на это забить?
💚 2 запроса одновременно читают баланс 1000₽, вычитают по 600₽ и сохраняют - что окажется в бд?
"
Ну как? Выживешь в такой ситуации?
А ведь именно так сейчас выглядит рынок найма - эти вопросы взяты с реальных собесов😯
Рынок усложнился, и на вакансию джуна спрашивают как на синьора 3 года назад. Нужно реально шарить, и шарить глубоко, только на одних нейронках далеко не уедешь
Чтобы разобраться раз и навсегда со Spring, Kafka, Redis Паша Сорокин 18 декабря в 19:00 по МСК проведёт живой открытый урок для Java-разработчиков и тех, кто хочет им стать:
💚 За какие темы надо шарить, чтобы получить оффер на миддла
💚 В каком порядке и до какой глубины их изучать
💚 По каждой технологии (Spring Boot, HTTP, REST, Postgresql, Hibernate, микросервисы, Kafka, Redis) разберут как делать не надо и как делать надо
🟢 Ссылка на урок будет в закрытом канале урока
В этом же канале вас ждёт подарок - гайд "Roadmap из 11 шагов до ЗП в 200.000+"
P.S. Паша - ex Senior Dev в ВТБ с 6 годами коммерческого опыта, так что фигни не посоветует))
Похититель наклоняется к твоему уху и шепчет: "Или ты правильно отвечаешь на 3 вопроса, или пуля летит тебе прямиком в висок:
"
Ну как? Выживешь в такой ситуации?
А ведь именно так сейчас выглядит рынок найма - эти вопросы взяты с реальных собесов
Рынок усложнился, и на вакансию джуна спрашивают как на синьора 3 года назад. Нужно реально шарить, и шарить глубоко, только на одних нейронках далеко не уедешь
Чтобы разобраться раз и навсегда со Spring, Kafka, Redis Паша Сорокин 18 декабря в 19:00 по МСК проведёт живой открытый урок для Java-разработчиков и тех, кто хочет им стать:
В этом же канале вас ждёт подарок - гайд "Roadmap из 11 шагов до ЗП в 200.000+"
P.S. Паша - ex Senior Dev в ВТБ с 6 годами коммерческого опыта, так что фигни не посоветует))
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4🤔2👍1🤯1
Postgres 18 получил поддержку виртуальных вычисляемых колонок. Вычисляемые STORED-колонки в Postgres уже были несколько версий подряд.
Вычисляемые колонки позволяют:
• создавать колонку на основе других данных
• ссылаться на значения из других колонок
• заранее считать колляции или любые вычисления в базе, а не в приложении
Синтаксис GENERATED ALWAYS AS открывает выражение, а в конце указывается режим VIRTUAL или STORED.
Виртуальные вычисляемые колонки пересчитываются при каждом чтении, поэтому не подходят для тяжёлых вычислений. Для таких случаев лучше использовать STORED-колонку или даже expression index. Но они удобны, когда значение нужно редко и его логично вычислять на лету.
Пример:
👉 Java Portal
Вычисляемые колонки позволяют:
• создавать колонку на основе других данных
• ссылаться на значения из других колонок
• заранее считать колляции или любые вычисления в базе, а не в приложении
Синтаксис GENERATED ALWAYS AS открывает выражение, а в конце указывается режим VIRTUAL или STORED.
Виртуальные вычисляемые колонки пересчитываются при каждом чтении, поэтому не подходят для тяжёлых вычислений. Для таких случаев лучше использовать STORED-колонку или даже expression index. Но они удобны, когда значение нужно редко и его логично вычислять на лету.
Пример:
CREATE TABLE products (
id serial PRIMARY KEY,
price numeric,
tax_rate numeric DEFAULT 0.05,
total_price numeric GENERATED ALWAYS AS (price * (1 + tax_rate)) VIRTUAL
);
Please open Telegram to view this post
VIEW IN TELEGRAM
❤1