es
Feedback

¡No caigas en manos de tramposos! Telemetrio encuentra y marca estos canales 👉 Si quieres ver la etiqueta, suscríbete

Библиотека Java разработчика

Библиотека Java разработчика

Ir al canal en Telegram

📚 Лайфхаки, приёмы и лучшие практики для Java-разработчиков. Всё, что ускорит код и прокачает навыки. Java, Spring, Maven, Hibernate. По всем вопросам @evgenycarter РКН clck.ru/3KoGeP

Mostrar más

📈 Análisis del canal de Telegram Библиотека Java разработчика

El canal Библиотека Java разработчика (@bookjava) en el segmento lingüístico de Ruso es un actor destacado. Actualmente la comunidad reúne a 10 005 suscriptores, ocupando la posición 12 110 en la categoría Tecnologías y Aplicaciones y el puesto 63 455 en la región Rusia.

📊 Métricas de audiencia y dinámica

Desde su creación el невідомо, el proyecto ha mostrado un crecimiento acelerado, reuniendo a 10 005 suscriptores.

Según los últimos datos del 25 octubre, 2026, el canal mantiene una actividad estable. En los últimos 30 días la variación de miembros fue de -54, y en las últimas 24 horas de -2, conservando un alto alcance.

  • Estado de verificación: No verificado
  • Tasa de interacción (ER): El promedio de interacción de la audiencia es 7.79%. Durante las primeras 24 horas tras publicar, el contenido suele obtener 3.74% de reacciones respecto al total de suscriptores.
  • Alcance de las publicaciones: Cada publicación recibe en promedio 780 visualizaciones. En el primer día suele acumular 374 visualizaciones.
  • Reacciones e interacción: La audiencia responde de forma activa: el promedio de reacciones por publicación es 4.
  • Intereses temáticos: El contenido se centra en temas clave como string, интерфейс, строка, boot, api.

📝 Descripción y política de contenido

El autor describe el recurso como un espacio para expresar opiniones subjetivas:
“📚 Лайфхаки, приёмы и лучшие практики для Java-разработчиков. Всё, что ускорит код и прокачает навыки. Java, Spring, Maven, Hibernate. По всем вопросам @evgenycarter РКН clck.ru/3KoGeP”

Gracias a la alta frecuencia de actualizaciones (últimos datos recibidos el 26 octubre, 2026), el canal mantiene la vigencia y un amplio alcance. La analítica demuestra que la audiencia interactúa activamente con el contenido, lo que lo convierte en un punto de referencia dentro de la categoría Tecnologías y Aplicaciones.

10 005
Suscriptores
-224 horas
-97 días
-5430 días
Atraer Suscriptores
oct '26
octubre '26
+21
en 0 canales
septiembre '26
+27
en 0 canales
Get PRO
agosto '26
+17
en 0 canales
Get PRO
julio '26
+20
en 0 canales
Get PRO
junio '26
+46
en 0 canales
Get PRO
mayo '26
+64
en 0 canales
Get PRO
abril '26
+27
en 0 canales
Get PRO
marzo '26
+28
en 0 canales
Get PRO
febrero '26
+39
en 0 canales
Get PRO
enero '26
+43
en 1 canales
Get PRO
diciembre '25
+16
en 0 canales
Get PRO
noviembre '25
+72
en 31 canales
Get PRO
octubre '25
+47
en 1 canales
Get PRO
septiembre '25
+61
en 36 canales
Get PRO
agosto '25
+55
en 0 canales
Get PRO
julio '25
+63
en 27 canales
Get PRO
junio '25
+44
en 19 canales
Get PRO
mayo '25
+65
en 44 canales
Get PRO
abril '25
+90
en 38 canales
Get PRO
marzo '25
+78
en 38 canales
Get PRO
febrero '25
+100
en 31 canales
Get PRO
enero '25
+83
en 33 canales
Get PRO
diciembre '24
+116
en 34 canales
Get PRO
noviembre '24
+67
en 32 canales
Get PRO
octubre '24
+99
en 29 canales
Get PRO
septiembre '24
+131
en 28 canales
Get PRO
agosto '24
+97
en 18 canales
Get PRO
julio '24
+45
en 0 canales
Get PRO
junio '24
+99
en 23 canales
Get PRO
mayo '24
+234
en 18 canales
Get PRO
abril '24
+210
en 0 canales
Get PRO
marzo '24
+282
en 21 canales
Get PRO
febrero '24
+274
en 17 canales
Get PRO
enero '24
+329
en 23 canales
Get PRO
diciembre '23
+222
en 23 canales
Get PRO
noviembre '23
+117
en 16 canales
Get PRO
octubre '23
+136
en 18 canales
Get PRO
septiembre '23
+243
en 0 canales
Get PRO
agosto '23
+325
en 0 canales
Get PRO
julio '23
+322
en 0 canales
Get PRO
junio '23
+306
en 0 canales
Get PRO
mayo '23
+287
en 0 canales
Get PRO
abril '23
+271
en 0 canales
Get PRO
marzo '23
+603
en 0 canales
Get PRO
febrero '23
+153
en 0 canales
Get PRO
enero '23
+214
en 0 canales
Get PRO
diciembre '22
+206
en 0 canales
Get PRO
noviembre '22
+140
en 0 canales
Get PRO
octubre '22
+207
en 0 canales
Get PRO
septiembre '22
+226
en 0 canales
Get PRO
agosto '22
+288
en 0 canales
Get PRO
julio '22
+299
en 0 canales
Get PRO
junio '22
+278
en 0 canales
Get PRO
mayo '22
+315
en 0 canales
Get PRO
abril '22
+318
en 0 canales
Get PRO
marzo '22
+417
en 0 canales
Get PRO
febrero '22
+328
en 0 canales
Get PRO
enero '22
+245
en 0 canales
Get PRO
diciembre '21
+222
en 0 canales
Get PRO
noviembre '21
+172
en 0 canales
Get PRO
octubre '21
+323
en 0 canales
Get PRO
septiembre '21
+207
en 0 canales
Get PRO
agosto '21
+331
en 0 canales
Get PRO
julio '21
+310
en 0 canales
Get PRO
junio '21
+271
en 0 canales
Get PRO
mayo '21
+297
en 0 canales
Get PRO
abril '21
+328
en 0 canales
Get PRO
marzo '21
+419
en 0 canales
Get PRO
febrero '21
+436
en 0 canales
Get PRO
enero '21
+452
en 0 canales
Get PRO
diciembre '20
+7 112
en 0 canales
Fecha
Crecimiento de Suscriptores
Menciones
Canales
26 octubre0
25 octubre+1
24 octubre0
23 octubre+3
22 octubre+1
21 octubre+1
20 octubre+1
19 octubre+2
18 octubre+2
17 octubre0
16 octubre0
15 octubre+1
14 octubre0
13 octubre0
12 octubre+1
11 octubre+1
10 octubre0
09 octubre+3
08 octubre+2
07 octubre+1
06 octubre0
05 octubre0
04 octubre+1
03 octubre0
02 octubre0
01 octubre0
Publicaciones del Canal
🧠 Как быстро написать компаратор в Java и не забыть про null Часто нужно сортировать коллекции по какому-то полю. Вместо ста
🧠 Как быстро написать компаратор в Java и не забыть про null Часто нужно сортировать коллекции по какому-то полю. Вместо старых анонимных классов используем лямбды и статические методы из Comparator:

List<User> users = ...;

users.sort(Comparator
    .comparing(User::getName, Comparator.nullsLast(String::compareToIgnoreCase))
    .thenComparingInt(User::getAge)
);
📌 comparing — сравнивает по полю (например, name). 📌 nullsLast или nullsFirst — удобно обрабатывать возможные null. 📌 thenComparingInt — дополнительная сортировка (например, по возрасту). 💡 Такой подход краткий, читабельный и отлично работает с любыми полями, даже если они могут быть null. ⚠️ Никогда не забывай про null, особенно если сортируешь данные из БД или внешних источников. Ошибка NullPointerException во время сортировки может неожиданно прилететь в проде. 📲 Мы в MAX 👉@BookJava

2
Сегодня покажу вам интересный костыль, который до сих пор живёт в JDK и влияет на сортировку списков. 🧠 Если ты когда-нибудь
Сегодня покажу вам интересный костыль, который до сих пор живёт в JDK и влияет на сортировку списков. 🧠 Если ты когда-нибудь пробовал сортировать LinkedList через Collections.sort(), знай — под капотом происходит скрытая магия. 📌 Collections.sort(list) сначала проверяет, какой это список. Если это RandomAccess-list (например, ArrayList) — используется быстрый сортировщик (TimSort) прямо по массиву. ⚠️ Но если это LinkedList (или любой не-рандом-доступ список), внутри происходит... преобразование списка в массив! Сначала все элементы копируются в массив, потом сортируются, а затем результат обратно заливается в твой список. // Да, это реально работает так: List<Integer> list = new LinkedList<>(); // ...заполняем... Collections.sort(list); 💡 Почему так? Сортировка напрямую через LinkedList была бы очень медленной — доступ к элементам по индексу у него O(n), а не O(1) как у ArrayList. Поэтому JDK идёт на компромисс: временная потеря памяти, но ускорение времени сортировки. ⚠️ Следствие: если у тебя большой LinkedList, сортировка будет требовать двойную память: сначала весь список копируется в массив. Совет: Для больших коллекций, которые часто сортируются, используй ArrayList, либо готовься к затратам памяти. 📲 Мы в MAX 👉@BookJava
746
3
🗄 Вебинар: JDBC: как Java-приложения взаимодействуют с базами данных JDBC позволяет Java-приложениям работать с базами данны
🗄 Вебинар: JDBC: как Java-приложения взаимодействуют с базами данных JDBC позволяет Java-приложениям работать с базами данных. Разберём подключение, SQL-запросы, транзакции и обработку ошибок. 💬 О чём поговорим - Как подключиться к СУБД с помощью DriverManager и работать с Connection. - Как выполнять SQL-запросы через Statement и PreparedStatement и получать результаты через ResultSet. - Как управлять транзакциями: autocommit, commit и rollback. - Как использовать SQLException, чтобы разобраться в причинах ошибки при выполнении запроса. 🎯 Результат урока: - Вы разберётесь, как подключать Java-приложение к СУБД, выполнять SQL-запросы и работать с результатами. - Узнаете, как управлять транзакциями и обрабатывать ошибки при обращении к базе данных. 👉 Для участия зарегистрируйтесь: https://vk.cc/d33JSz Вебинар проходит в рамках старта курса «Java-разработчик», который помогает освоить современную Java-разработку: от основ и первых программ до серверных приложений, баз данных, Spring, контейнеров и очередей сообщений. Программа регулярно обновляется под требования рынка. 🚀 Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru
702
4
Что такое тернарный оператор выбора? Тернарный условный оператор ?: - оператор, которым можно заменить некоторые конструкции операторов if-then-else. Выражение записывается в следующей форме: условие ? выражение1 : выражение2 Если условие выполняется, то вычисляется выражение1 и его результат становится результатом выполнения всего оператора. Если же условие равно false, то вычисляется выражение2 и его значение становится результатом работы оператора. Оба операнда выражение1 и выражение2 должны возвращать значение одинакового (или совместимого) типа. 📲 Мы в MAX 👉@BookJava
684
5
🧠 10 правил безопасного Java-приложения: 1️⃣ Валидация на всех уровнях. 📌 Всегда проверяй входные данные (API, формы, запро
🧠 10 правил безопасного Java-приложения: 1️⃣ Валидация на всех уровнях. 📌 Всегда проверяй входные данные (API, формы, запросы к БД). Используй Bean Validation (@Valid, @NotNull). 2️⃣ Используй PreparedStatement. ⚠️ Никогда не конкатенируй SQL-запросы напрямую, чтобы избежать SQL-инъекций. 3️⃣ Не раскрывай детали исключений. 📌 Отправляй клиенту общий код ошибки, а детали логируй. 4️⃣ Скрывай конфигурацию. 💡 Используй application.yml с переменными окружения для чувствительных данных (пароли, ключи API). 5️⃣ Ограничивай доступ. 📌 Spring Security — твой друг. Используй @PreAuthorize и грамотно настраивай роли и права доступа. 6️⃣ Безопасная сериализация. ⚠️ Избегай Java-стандартной сериализации. Предпочитай JSON (Jackson) с явными DTO. 7️⃣ Используй актуальные версии библиотек. 📌 Регулярно проверяй зависимости (dependency-check), чтобы избежать известных уязвимостей. 8️⃣ Грамотно логируй. 💡 Не логируй пароли, токены и персональные данные. Используй SLF4J с Logback, настрой уровень логов. 9️⃣ Безопасные куки и заголовки. 📌 Используй атрибуты куки: Secure, HttpOnly, SameSite. Spring Security поможет тебе настроить это быстро. 🔟 Настрой Security Headers. 📌 Используй заголовки: * X-Frame-Options: DENY * X-Content-Type-Options: nosniff * Content-Security-Policy (CSP) Безопасность — это не разовая задача, а процесс 💡 📲 Мы в MAX 👉@BookJava
889
6
🧠 Проверяешь аргументы вручную? Используй мощь системы типов Java! 📌 Ситуация: часто в методах видишь явные проверки вроде:
🧠 Проверяешь аргументы вручную? Используй мощь системы типов Java! 📌 Ситуация: часто в методах видишь явные проверки вроде: public void process(User user) { if (user == null || user.getName() == null) { throw new IllegalArgumentException("User или его имя не могут быть null"); } // код обработки... } ⚠️ Это шумно и ненадежно: легко пропустить проверку или некорректно сформулировать сообщение. 💡 Современный подход (Java 17+): явно обозначь контракт метода через типы и аннотации, и пусть JVM делает проверки автоматически! Используй стандартные средства: import java.util.Objects; public void process(User user) { Objects.requireNonNull(user, "User не должен быть null"); Objects.requireNonNull(user.getName(), "Имя пользователя не должно быть null"); // код обработки... } или лаконично через Lombok: import lombok.NonNull; public void process(@NonNull User user) { // Lombok автоматически вставит проверку на null } 🔸 Преимущества: * Ясность кода и контракта. * Меньше boilerplate и человеческого фактора. * Fail fast: сразу ловим ошибки, не откладывая. 🧠 Запомни: чем строже твоя система типов и контрактов, тем меньше неожиданностей в продакшене. 📲 Мы в MAX 👉@BookJava
816
7
🚀 Подборка полезных IT каналов в Max Системное администрирование, DevOps 📌 https://max.ru/i_odmin Все для системного администратора https://max.ru/bash_srv Bash Советы https://max.ru/sysadminof Книги для админов, полезные материалы https://max.ru/i_odmin_book Библиотека Системного Администратора https://max.ru/i_devops DevOps: Пишем о Docker, Kubernetes и др. https://max.ru/tipsysdmin Типичный Сисадмин https://max.ru/channel_win_sysadmin Системный Администратор Windows https://max.ru/channel_linux_admin Linux: Системный администратор https://max.ru/channel_linuxmod Linux https://max.ru/channel_i_linux Системный администратор https://max.ru/channel_devopslib DevOps, SRE, Sysadmin https://max.ru/channel_devops_star DevOps Star (Звезда Девопса) Excel лайфхак 📌 https://t.me/Excel_lifehack Excel лайфхак Английский с нуля 🇬🇧 https://max.ru/UchuEnglish 1C разработка 📌 https://max.ru/odin1c_rus Cтатьи, курсы, советы, шаблоны кода 1С https://max.ru/channel_DevLab1C 1С:Предприятие 8 Программирование C++📌 https://max.ru/cpp_lib Библиотека C/C++ разработчика https://max.ru/channel_cpp_geek C++ geek Программирование Go📌 https://max.ru/golang_lib Библиотека Go (Golang) разработчика Программирование React📌 https://max.ru/react_lib React Программирование Rust📌 https://max.ru/channel_rust_lib Программирование Python 📌 https://max.ru/python_of Python академия. https://max.ru/BookPython Библиотека Python разработчика Java разработка 📌 https://max.ru/bookjava Библиотека Java разработчика https://max.ru/channel_java_geek Java Geek GitHub Сообщество 📌 https://max.ru/githublib Интересное из GitHub Базы данных (Data Base) 📌 https://max.ru/database_info Все про базы данных Фронтенд разработка 📌 https://max.ru/frontend_1 Подборки для frontend разработчиков Библиотеки 📌 https://max.ru/programmist_of Книги по программированию https://max.ru/proglb Библиотека программиста https://max.ru/bfbook Книги для программистов Программирование 📌 https://max.ru/bookflow Лекции, видеоуроки, доклады с IT конференций https://max.ru/itmozg Программисты, дизайнеры, новости из мира IT https://max.ru/php_lib Библиотека PHP программиста 👨🏼‍💻👩‍💻 Шутки программистов 📌 https://max.ru/itumor Шутки программистов Защита, взлом, безопасность 📌 https://max.ru/thehaking Канал о кибербезопасности https://max.ru/xakkep_1 Хакер Free Книги, статьи для дизайнеров 📌 https://max.ru/odesigners Статьи, книги для дизайнеров Математика 📌 https://max.ru/Pomatematike Канал по математике https://max.ru/phismat_1 Обучающие видео, книги по Физике и Математике Вакансии в IT📌 https://max.ru/progjob https://max.ru/channel_rabotait Мир технологий 📌 https://max.ru/mir_teh Канал для любознательных Городские📌 https://max.ru/piterspb_78 Свежие новости Санкт-Петербурга https://max.ru/mockva_life Свежие новости Москвы https://max.ru/piterspb Питер Новости: Санкт-Петербург / СПБ / ДТП https://max.ru/channel_krasnodar_novosty Краснодар Новости https://max.ru/channel_novosibirsk_novosti Новосибирск https://max.ru/channel_samara_novosti Новости Самары https://max.ru/channel_ekaterinburg_novosti Новости Екатеринбурга https://max.ru/channel_kazan_novosti Новости Казани https://max.ru/channel_omsk_novosti Новости Омска https://max.ru/channel_moskva_24 Москва 24
627
8
📌 Обход коллекций в Java: делаем правильно! Часто вижу, как разработчики по привычке используют старый подход с циклом for.
📌 Обход коллекций в Java: делаем правильно! Часто вижу, как разработчики по привычке используют старый подход с циклом for. Сегодня напомню оптимальные способы перебора коллекций в Java. 🧠 1. Foreach (Java 5+) Коротко, ясно, подходит для большинства задач: for (String item : collection) { // обработка элемента } 🧠 2. Метод forEach (Java 8+) Отлично подходит для функционального стиля: collection.forEach(item -> { // обработка элемента }); ⚠️ Важно: нельзя модифицировать саму коллекцию во время такого обхода! 🧠 3. Stream API (Java 8+) Идеален для сложной обработки с фильтрацией, маппингом и т.д.: collection.stream() .filter(Objects::nonNull) .map(String::toUpperCase) .forEach(System.out::println); 💡 Что выбрать? * Простой перебор? Используй цикл foreach. * Нужно быстро и функционально? collection.forEach(). * Сложные манипуляции? Только Stream API. 📌 Используйте современные подходы, это читаемость и удобство поддержки вашего кода! 📲 Мы в MAX 👉@BookJava
784
9
📌 Stream API: забудьте про peek() Метод peek() в Java Stream API выглядит удобным для отладки, но его использование в реальн
📌 Stream API: забудьте про peek() Метод peek() в Java Stream API выглядит удобным для отладки, но его использование в реальном коде часто приводит к проблемам. ⚠️ Почему не стоит полагаться на peek()? * peek() — промежуточная операция, которая не гарантирует вызов функции для каждого элемента стрима. * Поведение зависит от терминальной операции: например, при некоторых оптимизациях JDK (особенно в параллельных стримах) вызов peek() может быть пропущен или работать непредсказуемо. 💡 Пример опасного кода: List<String> names = Stream.of("Java", "Spring", "Hibernate") .peek(System.out::println) // 👈 анти-паттерн! .collect(Collectors.toList()); 🧠 Лучший подход: используйте peek() исключительно для дебага, но никогда — для изменения состояния или важных операций. ✅ Правильная замена: Если нужно выполнить действие над каждым элементом, используйте явный и безопасный подход: List<String> names = Stream.of("Java", "Spring", "Hibernate") .map(name -> { log.info("Processing: {}", name); // или другая логика return name; }) .collect(Collectors.toList()); Или вообще вынесите логику за пределы стрима. 🧹 Держите код понятным и безопасным — забудьте про peek(). 📲 Мы в MAX 👉@BookJava
841
10
🧠 Dependency Inversion Principle (D в SOLID) Зависимости должны идти от высокоуровневой политики к низкоуровневым деталям, а не наоборот. Абстракции — хозяева, реализации — обслуживающий персонал. 📌 Коротко о сути * Модули верхнего уровня (бизнес-логика) зависят только от интерфейсов/абстракций. * Модули нижнего уровня (база, сеть, файлы) также зависят от тех же абстракций. * Сами абстракции не знают ничего о деталях, тем самым разрывая «бетонную» сцепку между слоями. 💡 Мини-пример (Java 17+, Spring Boot 3+) // 1️⃣ Абстракция — контракт public interface NotificationSender { void send(Message msg); } // 2️⃣ Верхний уровень — бизнес-служба @Service public class BillingService { private final NotificationSender sender; public BillingService(NotificationSender sender) { this.sender = sender; // зависим от контракта } public void bill(Client c) { // ... sender.send(new Message("Invoice #42")); } } // 3️⃣ Низкий уровень — деталь @Component public class EmailSender implements NotificationSender { public void send(Message msg) { // SMTP-магия } } BillingService может жить в модульном jar без spring-email-starter и SMTP-кода — протестировать его теперь элементарно. ⚠️ Где рождаются проблемы 1. Путаница DI container ≠ DIP IoC/DI-фреймворк (Spring, CDI) — лишь удобный способ «сращивать» зависимости, но принцип работает и без контейнера (чистый constructor injection). 2. Абстракции ради галочки Интерфейс OneImplService с единственной реализацией ломает читаемость, тесты и автоконфиг 📉. ➜ Создавай абстракцию, когда реально нужны сменяемость, тестируемость или расширяемость. 3. Утечки деталей Если интерфейс таскает DTO из слоя хранения, ты всё ещё «протёк» к базе. Держи контракты чистыми. 4. Слепая вера в фреймворк Жизненный цикл бинов, прокси, lazy-init — магия мешает понимать, кто кем владеет. ➜ Всегда можешь собрать объект вручную в юнит-тесте. Если сложно — запах нарушения DIP. 5. Слишком много уровней абстракций «Контроллер → сервис → менеджер → порт → адаптер → репозиторий» превращает код в матрёшку. Дизайн важнее количества слоёв. 📝 Практические советы * Используй constructor injection по умолчанию. Поле final = явная зависимость. * Группируй интерфейсы по use-case, а не по технологии (например, TransferPort, а не JdbcTransferRepository). * В тестах не мокай фреймворк — мокай контракт. * Для одноразовых реализаций начни с class. Если появится второй вариант — быстро вынесешь интерфейс (IDE поможет). * Проверка себя: можно ли запустить модуль верхнего уровня без нижнего? Если да — DIP соблюдён. 💬 Итог DIP — это не про «везде интерфейсы» и не про «подключи Spring». Это про правильное направление зависимостей, которое делает код гибким, тестируемым и не заложником технологий. А проблемы возникают, когда путают инструмент с принципом и забывают, что абстракция должна прятать детали, а не выпячивать их. 📲 Мы в MAX 👉@BookJava
815
11
Три похожих слова в Java — final, finally, finalize — но смысл у них совершенно разный. Разберёмся 🧠 🔒 final Ключевое слово
Три похожих слова в Java — final, finally, finalize — но смысл у них совершенно разный. Разберёмся 🧠 🔒 final Ключевое слово. Используется для ограничений: * final class — нельзя наследовать. * final method — нельзя переопределить. * final variable — нельзя изменить значение (один раз присвоил — всё). 📌 Особенно важно для immutability и thread-safety. final int x = 10; x = 20; // ошибка компиляции 🧯 finally Блок в конструкции try-catch-finally. Выполняется всегда, даже если был return или exception. 💡 Используется для освобождения ресурсов: закрытия потоков, соединений и т.д. try { // что-то может выбросить исключение } catch (Exception e) { // обработка ошибки } finally { // всегда выполнится } ⚰️ finalize() Метод из Object, вызывался перед удалением объекта сборщиком мусора. ⚠️ УСТАРЕЛ с Java 9, удалён в Java 18. Не используй. 🔪 Непредсказуем, плохо работает, тормозит GC. Вместо него — AutoCloseable и try-with-resources. @Override protected void finalize() throws Throwable { System.out.println("До свидания..."); } 🧠 Важно не путать: * final — про нельзя менять * finally — про всегда выполнится * finalize — про устаревший и бесполезный метод 📲 Мы в MAX 👉@BookJava
988
12
🧠 Ленивая инициализация через Supplier — элегантная альтернатива double-checked locking Когда нужно отложить создание тяжёло
🧠 Ленивая инициализация через Supplier — элегантная альтернатива double-checked locking Когда нужно отложить создание тяжёлого объекта до первого обращения, многие вспоминают double-checked locking: private volatile SomeHeavyObject obj; public SomeHeavyObject getObj() { if (obj == null) { synchronized (this) { if (obj == null) { obj = new SomeHeavyObject(); } } } return obj; } ⚠️ Многословно, хрупко, легко ошибиться. Есть лучше. 📌 Современный подход — использовать Supplier с ленивой инициализацией: private final Supplier<SomeHeavyObject> lazyObj = Suppliers.memoize(SomeHeavyObject::new); public SomeHeavyObject getObj() { return lazyObj.get(); } 💡 Suppliers.memoize — из Guava. Он гарантирует потокобезопасную инициализацию один раз при первом вызове get(). Плюсы: — Читается за секунду — Потокобезопасно — Нет дублирования кода — Легко тестировать и заменять 🔁 Альтернатива в чистой Java: использовать AtomicReference и updateAndGet, но это уже длиннее и менее выразительно. Если используешь Spring — можно просто обернуть бин в @Lazy. Но вне Spring, в обычных Java-приложениях или утилитах — Supplier с memoize() идеален. 📲 Мы в MAX 👉@BookJava
984
13
Что такое механизм try-with-resources? Механизм try-with-resources в Java — это конструкция, которая упрощает работу с ресурс
Что такое механизм try-with-resources? Механизм try-with-resources в Java — это конструкция, которая упрощает работу с ресурсами, требующими закрытия (например, файлы, сокеты, соединения с БД и т.д.). Он автоматически закрывает ресурсы после завершения блока try, избавляя от необходимости писать finally вручную. 📌 Поддерживается с Java 7 📌 Ресурсы должны реализовывать интерфейс AutoCloseable 💡 Пример: try (BufferedReader reader = new BufferedReader(new FileReader("file.txt"))) { String line = reader.readLine(); System.out.println(line); } catch (IOException e) { e.printStackTrace(); } // reader будет закрыт автоматически, даже если произойдёт исключение 🧠 Почему это важно: * Уменьшает boilerplate-код * Исключает утечки ресурсов * Упрощает обработку исключений ⚠️ Совет: С Java 9 можно использовать уже объявленные переменные, если они final или effectively final: BufferedReader reader = new BufferedReader(new FileReader("file.txt")); try (reader) { System.out.println(reader.readLine()); } 📲 Мы в MAX 👉@BookJava
1 074
14
📌 picocli — это современная библиотека для создания CLI-приложений на Java. Она упрощает разработку командных интерфейсов, о
📌 picocli — это современная библиотека для создания CLI-приложений на Java. Она упрощает разработку командных интерфейсов, обеспечивая: * Автоматическую генерацию --help и --version * Поддержку подкоманд (как в git commit, git push) * Аргументы, параметры, опции с короткими и длинными флагами (-v, --verbose) * Интеграцию с GraalVM (подходит для нативной компиляции) * Поддержку аннотаций (аннотируй POJO — и готово!) * Автоматическую валидацию аргументов * Цветной вывод и гибкое форматирование * Интерактивный режим и автодополнение Проект активно развивается, полностью документирован и используется в сотнях продакшн-проектов. Если ты ищешь мощную и простую в использовании CLI-библиотеку на Java — picocli отличный выбор. https://github.com/remkop/picocli 📲 Мы в MAX 👉@BookJava
1 041
15
Double-brace инициализация в Java — это идиома, которая используется для инициализации коллекций (и иногда других объектов) в
Double-brace инициализация в Java — это идиома, которая используется для инициализации коллекций (и иногда других объектов) в краткой форме. Она выглядит как две открывающие фигурные скобки подряд {{ и имеет специфическое поведение. Пример: import java.util.*; List<String> list = new ArrayList<String>() {{ add("one"); add("two"); add("three"); }}; Как это работает: Double-brace инициализация — это комбинация двух конструкций: 1. Анонимный внутренний класс: new ArrayList<String>() { ... } Создаётся новый безымянный подкласс ArrayList. 2. Инициализатор экземпляра: {{ ... }} Это блок, который выполняется при создании объекта. В него можно вставлять вызовы методов (например, add()). Преимущества: * Компактный и удобочитаемый синтаксис для заполнения коллекций. * Можно использовать в полях final, например: private static final Set<String> set = new HashSet<>() {{ add("A"); add("B"); }}; Недостатки: 1. Создаётся лишний анонимный класс — это увеличивает количество байткода и может мешать сериализации. 2. Утечки памяти — если такой класс находится внутри внешнего класса, он может неявно хранить ссылку на него. 3. Читаемость — не все разработчики знают, как это работает, и это может сбивать с толку. 4. Нарушение принципов OOP — логика инициализации размещается в конструкторе, который не явно виден. Альтернативы: Java 8+ (через Stream и Collectors): List<String> list = Stream.of("one", "two", "three") .collect(Collectors.toList()); Статический метод инициализации: public static List<String> createList() { List<String> list = new ArrayList<>(); list.add("one"); list.add("two"); return list; } Java 9+ (immutable): List<String> list = List.of("one", "two", "three"); Set<String> set = Set.of("A", "B"); Вывод: Double-brace инициализация — это удобный, но потенциально опасный трюк, который не рекомендуется использовать в продакшене. Лучше предпочесть более читаемые и безопасные альтернативы, особенно с учётом новых возможностей Java 8+. 📲 Мы в MAX 👉@BookJava
998
16
🧠@Value vs @ConfigurationProperties — не выбирай наобум Оба способа хороши для конфигурации, но используют их по-разному. И
🧠@Value vs @ConfigurationProperties — не выбирай наобум Оба способа хороши для конфигурации, но используют их по-разному. И если ты всё ещё везде пихаешь @Value, держи краткий гайд, когда лучше что: 📌 @Value — просто, но не гибко: @Value("${my.prop}") private String value; ✅ Хорошо для единичных значений ❌ Плохо для сложных структур, списков, валидации ❌ Трудно покрыть тестами (без TestPropertySource) ❌ Нет биндинга по префиксу → нет группировки 📌 @ConfigurationProperties — сила и масштаб: @ConfigurationProperties(prefix = "app.feature") public class FeatureProperties { private boolean enabled; private List<String> items; } 💡 Используй с @EnableConfigurationProperties или аннотируй как @Component ✅ Удобно группировать и документировать ✅ Работает с вложенными структурами, коллекциями ✅ Поддерживает JSR-303 валидацию (@Validated) ✅ Легче мокать в тестах ✅ Интеграция с Spring Boot Actuator (/actuator/configprops) ⚠️ Не смешивай: не нужно тянуть @Value внутрь @ConfigurationProperties — это антипаттерн. Если конфигурация простая — @Value норм. Но как только появляется структура, коллекции, логика — всегда используй @ConfigurationProperties. 📲 Мы в MAX 👉@BookJava
895
17
🧠 Трюк с @EventListener в Spring — убираем лишний @TransactionalEventListener Когда тебе нужно обрабатывать события в рамках
🧠 Трюк с @EventListener в Spring — убираем лишний @TransactionalEventListener Когда тебе нужно обрабатывать события в рамках транзакции, мы часто пишем: @TransactionalEventListener public void handleEvent(MyEvent event) { // ... } ⚠️ Но есть нюанс: @TransactionalEventListener по умолчанию срабатывает после коммита. Иногда это не очевидно и вызывает баги, особенно если ожидаешь, что событие обработается внутри транзакции. 📌 Альтернатива: обычный @EventListener, но вместе с TransactionSynchronizationManager. 💡 Сниппет: @Component public class MyEventHandler { @EventListener public void handle(MyEvent event) { if (TransactionSynchronizationManager.isActualTransactionActive()) { TransactionSynchronizationManager.registerSynchronization( new TransactionSynchronizationAdapter() { @Override public void afterCommit() { // обработка события после коммита } } ); } else { // fallback: нет активной транзакции — выполняем сразу } } } 📎 Плюсы: — Лучше контроль: ты сам решаешь, когда обрабатывать (до/после/вне транзакции) — Можно централизовать поведение через utility-метод — Гибкость: логика обработки не зависит от аннотаций Spring'а ⚠️ Минус: чуть больше кода, но понятнее поведение. 📲 Мы в MAX 👉@BookJava
890
18
👩‍💻 HTTP-сервер на чистой Java за 30 минут Приглашаем на открытый урок. 🗓 21 сентября в 20:00 МСК 🆓 Бесплатно. Урок в рам
👩‍💻 HTTP-сервер на чистой Java за 30 минут Приглашаем на открытый урок. 🗓 21 сентября в 20:00 МСК 🆓 Бесплатно. Урок в рамках старта курса «Java разработчик. Продвинутый уровень». Разберем, как браузер общается с сервером, и создадим работающий HTTP-сервис без Spring и сторонних библиотек. О чем поговорим: ✔️ Как устроен HTTP-запрос ✔️ Создадим сервер на Java ✔️ Добавим несколько адресов ✔️ Откроем результат в браузере ✔️ Разберём, что скрывает Spring 🔗 Ссылка на регистрацию: https://vk.cc/d1sLwn Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
1 097
19
🧠 Как не словить LazyInitializationException в Spring Boot + Hibernate Одна из самых частых ошибок при работе с JPA: org.hib
🧠 Как не словить LazyInitializationException в Spring Boot + Hibernate Одна из самых частых ошибок при работе с JPA: org.hibernate.LazyInitializationException: failed to lazily initialize a collection 📌 Причина: лениво загружаемая коллекция (LAZY) обращается к БД вне транзакции — например, в слое контроллера или после закрытия Session. 💡 Как избежать? ✅ Решение 1: @Transactional в сервисе Убедитесь, что вы обращаетесь к ленивым коллекциям внутри метода с @Transactional: @Transactional public UserDto getUser(Long id) { User user = userRepository.findById(id) .orElseThrow(); // OK: коллекция friends будет инициализирована в транзакции return new UserDto(user.getName(), user.getFriends()); } ⚠️ Не используйте @Transactional в контроллерах - это плохая практика. ✅ Решение 2: Fetch Join Подгрузите нужные данные сразу через JOIN FETCH: @Query("SELECT u FROM User u LEFT JOIN FETCH u.friends WHERE u.id = :id") Optional<User> findByIdWithFriends(@Param("id") Long id); 📌 Плюс: 1 запрос вместо N (N+1 проблема решается). 📌 Минус: может быть избыточная загрузка, особенно с большими коллекциями. ✅ Решение 3: DTO проекция Лучший способ в большинстве случаев - проецировать сразу в DTO: @Query(""" SELECT new com.example.UserDto(u.name, f.name) FROM User u LEFT JOIN u.friends f WHERE u.id = :id """) List<UserDto> findUserWithFriendNames(@Param("id") Long id); 📌 Выгружает только нужные данные. Быстро, безопасно, эффективно. Ленивая инициализация - ок, если вы контролируете границы транзакций. Проекции и fetch join - ваши лучшие друзья, если нужен контроль и производительность. 📲 Мы в MAX 👉@BookJava
895
20
📌 Java Collections 📲 Мы в MAX 👉@BookJava+2
📌 Java Collections 📲 Мы в MAX 👉@BookJava
1 047