📚 Лайфхаки, приёмы и лучшие практики для Java-разработчиков. Всё, что ускорит код и прокачает навыки. Java, Spring, Maven, Hibernate. По всем вопросам @evgenycarter РКН clck.ru/3KoGeP
Используем Lombok правильно: Разбираемся с @Slf4j
Сегодня я расскажу вам о @Slf4j
из библиотеки Lombok и о том, как его правильно использовать, чтобы ваш код стал чище и удобнее.
Что такое @Slf4j
?
Это аннотация, которая добавляет в ваш класс статическое поле логгера org.slf4j.Logger. Вместо того чтобы писать:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MyService {
private static final Logger log = LoggerFactory.getLogger(MyService.class);
}
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class MyService {
}
log.info("Приложение запущено");
log.error("Произошла ошибка: {}", exception.getMessage());
@Slf4j
использует SLF4J API, поэтому вам все равно потребуется подключить реализацию логирования, например Logback:
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.11</version>
</dependency>
@Log
— для java.util.logging@Log4j
— для Apache Log4j@Log4j2
— для Log4j2 debug
для отладки, info
для полезных сообщений, warn
для предупреждений и error
для ошибок. @Slf4j
— это удобный инструмент, который избавляет от лишнего кода и упрощает работу с логированием. Если вы еще не используете Lombok для логирования, самое время попробовать! 🚀 Используем Optional правильно в Java
Сегодня разберем Optional – мощный инструмент, который помогает избежать NullPointerException. Но многие используют его неправильно! Давайте посмотрим, как его применять эффективно.
❌ Как делать НЕ надо:
Optional<String> optional = Optional.ofNullable(getValue());
if (optional.isPresent()) {
System.out.println(optional.get());
}
Optional.ofNullable(getValue()).ifPresent(System.out::println);
String value = Optional.ofNullable(getValue()).orElse("Default Value");
Optional
: Optional
пуст null
. ⚡️ Квиз на знание Java
Пройти тестирование — сложно! А ты справишься?
22 вопроса, 30 минут
Проверь себя - пройди квиз и оцени свой уровень навыков, а также свою готовность к обучению на курсе — «Java Developer. Advanced» от Отус.
👩💻 На курсе ты научишься профилировать приложения, настраивать GC, работать с реактивными подходами и мониторить метрики в Grafana. Пройдешь весь путь от JVM до Kubernetes, научишься анализировать «горячие точки», оптимизировать приложения и настраивать интеграции с Prometheus.
➡️ ПРОЙТИ ТЕСТ: https://vk.cc/cIZDax
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
👩💻 Вы — Java-разработчик, готовый к большему?
Повышение квалификации на курсе «Java Developer. Professional» — это путь от уверенного программиста до востребованного Middle+ специалиста.
Почему этот курс для вас?
— 96 часов практики и детального кода.
— Основы JVM: разберём byteCode и сборку мусора.
— Современные фреймворки: Spring WebFlux, Kafka, Kubernetes.
— Реальные задачи и код-ревью от экспертов.
Преподаватели с опытом в крупнейших компаниях помогут вам:
— Освоить многопоточность и реактивный Postgres.
— Решать задачи уровня Middle+ с уверенностью.
— Писать код быстрее, чище и без лишних багов.
🔥 До 28.02 скидка на все курсы 10%, кроме этого дарим промокод Javapro-02 который прибавляет к скидке еще 5% !!!
🎫 Курс можно приобрести в рассрочку
➡️ Последний шанс пройти тестирование и получить скидку! Не упустите возможность прокачать свои навыки и построить впечатляющую карьеру: https://vk.cc/cIX0s5
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
🚀 Параметры JVM: Какие ключевые стоит знать?
Сегодня я покажу вам самые важные параметры JVM, которые помогут вам оптимизировать работу вашего Java-приложения. Эти флаги влияют на производительность, управление памятью и отладку.
🔥 Управление памятью:
- -Xms<size>
– задает начальный размер кучи.
- -Xmx<size>
– задает максимальный размер кучи.
- -XX:NewRatio=<n>
– определяет соотношение между молодым и старым поколением.
- -XX:SurvivorRatio=<n>
– соотношение между Eden и Survivor.
⚡ Гаражная сборка (GC):
- -XX:+UseG1GC
– включает G1 Garbage Collector (по умолчанию в Java 9+).
- -XX:+UseParallelGC
– включает Parallel GC.
- -XX:+UseZGC
– включает экспериментальный ZGC (минимальная пауза).
- -XX:+UseShenandoahGC
– еще один GC с низкими задержками.
🛠️ Диагностика и отладка:
- -XX:+PrintGCDetails
– подробный вывод информации о сборке мусора.
- -XX:+HeapDumpOnOutOfMemoryError
– дамп памяти при OOM.
- -XX:HeapDumpPath=<path>
– указывает путь для дампа памяти.
- -XX:+ExitOnOutOfMemoryError
– завершает JVM при OOM.
🏎️ Оптимизация JIT:
- -XX:+TieredCompilation
– адаптивная компиляция кода.
- -XX:+UseStringDeduplication
– уменьшает использование памяти строками.
- -XX:+AlwaysPreTouch
– аллокация памяти заранее (полезно для больших heap'ов).
Попробуйте поэкспериментировать с этими параметрами и посмотрите, как они влияют на производительность вашего приложения!
Какие параметры JVM используете вы? Пишите в комментариях!
👉 @BookJava
⚡️👩💻 Освой Java с нуля и начни карьеру успешного разработчика!
Мечтаешь вкатиться в IT, но думаешь, что уже поздно? Java — язык, на котором работают крупнейшие компании мира! Тебе точно найдется место.
🦾 Наше обучение на курсе "Java-разработчик" — это 3 ступени, которые проведут тебя от новичка до уверенного Middle-разработчика. Ты освоишь Spring, Hibernate, PostgreSQL, Docker, Kafka, Kubernetes и другие актуальные технологии!
Программа составлена практикующими экспертами, а диплом OTUS востребован в ведущих IT-компаниях. Наш партнер — СберКорус, разработчик передовых цифровых решений!
👉 Оставь заявку и получи скидку на курс: https://vk.cc/cIVZFZ
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
📝 Разбираем @Transactional
в Spring: Где Подводные Камни?
Давайте обсудимм одну из самых популярных аннотаций в Spring — @Transactional
. Многие знают, что она используется для управления транзакциями, но не все понимают, как она работает под капотом и какие проблемы могут возникнуть. Давайте разбираться!
🔍 Как работает @Transactional
?
Когда вы помечаете метод @Transactional
, Spring проксирует этот метод и оборачивает его в транзакцию. Это значит, что до начала метода открывается транзакция, а после — либо коммитится (если нет ошибок), либо откатывается (если есть исключение).
Но тут важно помнить:
🔹 @Transactional
работает только на public методах (если используется Spring AOP).
🔹 Вызовы методов внутри одного класса не учитывают @Transactional
. Если вызвать метод, аннотированный @Transactional
, внутри другого метода того же класса, транзакция не создастся.
🔹 По умолчанию, транзакция откатывается только при RuntimeException. Если бросить checked
-исключение, Spring не откатит транзакцию.
⚠️ Распространённые ошибки
❌ Аннотация на private методе
Транзакция просто не будет работать, так как Spring AOP не перехватит вызов.
❌ Вызов @Transactional
метода внутри того же класса
Транзакция не создастся, так как вызов происходит без участия Spring Proxy. Решение — выносить такие методы в отдельный бин или использовать TransactionTemplate
.
❌ Неправильный rollback
Если в методе выбрасывается checked-исключение, Spring по умолчанию **не откатывает** транзакцию. Чтобы изменить это поведение, нужно явно указать `@Transactional(rollbackFor = Exception.class)
.
✅ Как избежать проблем?
✔️ Всегда ставьте @Transactional
на публичные методы.
✔️ Вызывайте @Transactional
-методы только через Spring-управляемые бины.
✔️ Контролируйте rollback через rollbackFor
.
✔️ Используйте propagation = REQUIRES_NEW
, если хотите создать новую независимую транзакцию.
Кто сталкивался с неожиданным поведением @Transactional
? Давайте обсудим в комментариях!
👉 @BookJava
📝 Советы по оптимизации Java кода: избавляемся от лишнего
Привет, друзья! Сегодня поговорим об оптимизации кода. Все мы знаем, что код должен быть не только работоспособным, но и читаемым, эффективным и поддерживаемым. Давайте разберем несколько типичных ошибок и способов их устранения.
🚀 1. Избегайте ненужного создания объектов
Частая ошибка — создавать объекты там, где можно использовать уже существующие.
❌ Плохо:
String str = new String("Hello"); // Избыточно
String str = "Hello"; // Используем строковый пул
Integer.valueOf()
вместо new Integer()
. StringBuilder
будет значительно быстрее.
String result = "";
for (int i = 0; i < 100; i++) {
result += i; // Создает новый объект String на каждой итерации
}
StringBuilder result = new StringBuilder();
for (int i = 0; i < 100; i++) {
result.append(i);
}
ArrayList
, если не нужна частая вставка/удаление элементов в середине списка. HashSet
, если важны уникальные значения и не нужен порядок. LinkedList
, если нужна частая вставка/удаление в середине списка.
List<Integer> numbers = List.of(1, 2, 3, 4, 5);
int sum = numbers.stream().reduce(0, Integer::sum);
int sum = 0;
for (int num : numbers) {
sum += num;
}
Подборка Telegram каналов для программистов
/channel/lifeproger Жизнь программиста. Авторский канал.
/channel/devopslib Библиотека девопса | DevOps, SRE, Sysadmin
/channel/rabota1C_rus 1С Работа
Системное администрирование 📌
/channel/sysadmin_girl Девочка Сисадмин
/channel/srv_admin_linux Админские угодья
/channel/linux_srv Типичный Сисадмин
/channel/linux_odmin Linux: Системный администратор
/channel/devops_star DevOps Star (Звезда Девопса)
/channel/i_linux Системный администратор
/channel/linuxchmod Linux
/channel/sys_adminos Системный Администратор
/channel/tipsysdmin Типичный Сисадмин (фото железа, было/стало)
/channel/sysadminof Книги для админов, полезные материалы
/channel/i_odmin Все для системного администратора
/channel/i_odmin_book Библиотека Системного Администратора
/channel/i_odmin_chat Чат системных администраторов
/channel/i_DevOps DevOps: Пишем о Docker, Kubernetes и др.
/channel/sysadminoff Новости Линукс Linux
1C разработка 📌
/channel/odin1C_rus Cтатьи, курсы, советы, шаблоны кода 1С
Программирование C++📌
/channel/cpp_lib Библиотека C/C++ разработчика
/channel/cpp_knigi Книги для программистов C/C++
/channel/cpp_geek Учим C/C++ на примерах
Программирование Python 📌
/channel/pythonofff Python академия. Учи Python быстро и легко🐍
/channel/BookPython Библиотека Python разработчика
/channel/python_real Python подборки на русском и английском
/channel/python_360 Книги по Python Rus
Java разработка 📌
/channel/BookJava Библиотека Java разработчика
/channel/java_360 Книги по Java Rus
/channel/java_geek Учим Java на примерах
GitHub Сообщество 📌
/channel/Githublib Интересное из GitHub
Базы данных (Data Base) 📌
/channel/database_info Все про базы данных
Мобильная разработка: iOS, Android 📌
/channel/developer_mobila Мобильная разработка
/channel/kotlin_lib Подборки полезного материала по Kotlin
Фронтенд разработка 📌
/channel/frontend_1 Подборки для frontend разработчиков
/channel/frontend_sovet Frontend советы, примеры и практика!
/channel/React_lib Подборки по React js и все что с ним связано
Разработка игр 📌
/channel/game_devv Все о разработке игр
Библиотеки 📌
/channel/book_for_dev Книги для программистов Rus
/channel/programmist_of Книги по программированию
/channel/proglb Библиотека программиста
/channel/bfbook Книги для программистов
/channel/books_reserv Книги для программистов
БигДата, машинное обучение 📌
/channel/bigdata_1 Data Science, Big Data, Machine Learning, Deep Learning
Программирование 📌
/channel/bookflow Лекции, видеоуроки, доклады с IT конференций
/channel/coddy_academy Полезные советы по программированию
/channel/rust_lib Полезный контент по программированию на Rust
/channel/golang_lib Библиотека Go (Golang) разработчика
/channel/itmozg Программисты, дизайнеры, новости из мира IT
/channel/php_lib Библиотека PHP программиста 👨🏼💻👩💻
/channel/nodejs_lib Подборки по Node js и все что с ним связано
/channel/ruby_lib Библиотека Ruby программиста
QA, тестирование 📌
/channel/testlab_qa Библиотека тестировщика
Шутки программистов 📌
/channel/itumor Шутки программистов
Защита, взлом, безопасность 📌
/channel/thehaking Канал о кибербезопасности
/channel/xakep_1 Статьи из "Хакера"
Книги, статьи для дизайнеров 📌
/channel/ux_web Статьи, книги для дизайнеров
Английский 📌
/channel/UchuEnglish Английский с нуля
Математика 📌
/channel/Pomatematike Канал по математике
/channel/phis_mat Обучающие видео, книги по Физике и Математике
Excel лайфхак📌
/channel/Excel_lifehack
/channel/tikon_1 Новости высоких технологий, науки и техники💡
/channel/mir_teh Мир технологий (Technology World)
Вакансии 📌
/channel/sysadmin_rabota Системный Администратор
/channel/progjob Вакансии в IT
⁉️👩💻Разрабатываете на Java, но проект на Spring превращается в черный ящик? Бины ведут себя непредсказуемо, конфигурация разрастается, а ошибка в одном модуле рушит всю систему.
Интервью на позицию Middle неудачно — не хватает уверенности в Spring.
🤝 Тем временем рынок требует специалистов, которые не просто знают Spring, а умеют строить продакшен-приложения с его помощью. Компании ищут разработчиков, которые понимают, как работают Spring Boot, Spring Security, Spring MVC и могут строить микросервисную архитектуру.
⚡️ На курсе «Разработчик на Spring Framework» мы закроем пробелы и дадим актуальные навыки. Практика на реальных кейсах, ревью заданий, тестовое собеседование — вы освоите Spring так, чтобы уверенно применять его в работе.
➡️ Пройдите вступительное тестирование и получите скидку на обучение: https://vk.cc/cIPLUU
🎫 Курс можно приобрести в рассрочку
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
В чем разница между Iterator и ListIterator?
— Iterator может итерироваться только вперед, а ListIterator может и вперед и назад.
— ListIterator имеет дополнительные методы previous()
, hasPrevious()
, add(), set()
.
— ListIterator позволяет получить индекс текущего элемента.
— ListIterator может начать итерацию с произвольного индекса списка, а Iterator только с начала.
— ListIterator можно получить только из объектов, реализующих List, а Iterator из любой коллекции.
— ListIterator является более функциональным и позволяет вносить изменения в список во время итерации, Iterator — только читать.
— Итераторы безопасны для использования в многопоточных приложениях, а ListIterator — нет.
👉@BookJava
🚀 Разбираемся с Optional
в Java: избегаем NullPointerException
!
Привет, друзья! Сегодня хочу поговорить о Optional
, который помогает нам избежать NullPointerException
и делает код чище.
❓ Что такое Optional
? Optional<T>
— это контейнер, который может содержать значение типа T
или быть пустым. Это альтернатива null
, которая явно указывает, что значение может отсутствовать.
🔥 Как использовать?
1️⃣ Создание Optional
:
Optional<String> optional = Optional.of("Hello, Java!");
null
, будет NullPointerException
. Optional
:
Optional<String> emptyOptional = Optional.empty();
null
:
Optional<String> nullableOptional = Optional.ofNullable(null);
null
, Optional
не упадёт, а просто будет пустым.
optional.isPresent(); // true
optional.isEmpty(); // false
ifPresent
:
optional.ifPresent(value -> System.out.println(value));
orElse
:
String result = optional.orElse("Значение по умолчанию");
orElseGet
:
String result = optional.orElseGet(() -> "Вычисленное значение");
String result = optional.orElseThrow(() -> new RuntimeException("Значение отсутствует!"));
Optional<String> filtered = optional.filter(val -> val.startsWith("Hello"));
map
:
Optional<Integer> length = optional.map(String::length);
Optional
— мощный инструмент, но не стоит злоупотреблять им везде. Используйте его в возвращаемых значениях, но не в полях и параметрах методов.Optional
? Делитесь в комментариях! 👇👇👇⚡️ В сети начали массово сливать курсы и книги известных онлайн школ по айти
Вот отсортированная база с тонной материала (постепенно пополняется):
БАЗА (4687 видео/книг):
(363 видео, 87 книги) — Python
(415 видео, 68 книги) — Frontend
(143 видео, 33 книги) — ИБ/Хакинг
(352 видео, 89 книги) — С/С++
(343 видео, 87 книги) — Java
(176 видео, 32 книги) — Git
(293 видео, 63 книги) — C#
(174 видео, 91 книги) — DevOps
(167 видео, 53 книги) — PHP
(227 видео, 83 книги) — SQL/БД
(163 видео, 29 книги) — Linux
(114 видео, 77 книги) — Сисадмин
(107 видео, 43 книги) — BA/SA
(181 видео, 32 книги) — Go
(167 видео, 43 книги) — Kotlin/Swift
(112 видео, 24 книги) — Flutter
(137 видео, 93 книги) — DS/ML
(113 видео, 82 книги) — GameDev
(183 видео, 37 книги) — Дизайн
(129 видео, 73 книги) — QA
(213 видео, 63 книги) — Rust
(121 видео, 24 книги) — 1С
(136 видео, 33 книги) — PM/HR
Скачивать ничего не нужно — все выложили в Telegram
⚔️Ваши микросервисы не дружат между собой?
Сначала один сервис завис, потом второй, а в логах — хаос. Конфиги разбросаны по разным файлам, API ломаются после каждого релиза, а тестировщики смотрят на вас как на главного злодея проекта.
👩💻 Есть способ навести порядок. Spring Cloud помогает микросервисам работать как единая система: управлять конфигурациями, находить друг друга без лишних костылей и не падать при каждом обновлении.
🦾Разберём, как это сделать, на открытом уроке «Экосистема Spring Cloud».
Когда: 25 февраля в 20:00 (мск).
Вы узнаете, как использовать Service Discovery, API Gateway и Config Server. А еще получите скидку на большое обучение «Java Developer. Advanced».
Не ждите, пока сервисы начнут воевать друг с другом.
🔗 Регистрируйтесь прямо сейчас: https://vk.cc/cIL61o
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
👩💻 Resilience4j. RateLimiter
Приглашаем на открытый урок.
🗓 24 февраля в 20:00 МСК
🆓 Бесплатно. Урок в рамках старта курса«Java Developer. Professional».
Где мы разберем:
✔️Что такое RateLimiter?
✔️Настройка и особенности.
Урок будет полезен тем, кто хочет:
✔️Защитить приложения от пиковых нагрузок и обеспечить высокую доступность.
✔️Использовать ключевые инструменты Resilience4j для управления трафиком.
✔️Глубже понять, как писать надёжные микросервисы и оптимизировать их под реальные сценарии.
В результате урока вы:
✔️Разберётесь, как работает RateLimiter и в чём его польза при ограничении запросов.
✔️Получите несколько примеров настройки и сможете применять эти приёмы в базовых сценариях.
Спикер Сергей Петрелевич — опытный Java/Kotlin-разработчик и преподаватель.
🔗 Ссылка на регистрацию: https://vk.cc/cIJZkNРеклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
🦾👩💻Хардкорный тест по языку Java👩💻🦾
👩💻 Пройдите тест из 21 вопроса и проверьте, насколько вы готовы к обучению на углубленном курсе «Разработчик на Spring Framework» от OTUS.
Сможете сдать - пройдете на курс по спеццене!
💻 За 5 месяцев обучения вы освоите современные возможности Spring, научитесь быстро проходить путь от идеи до production-grade, создавать Web-приложения на микросервисной архитектуре и решать высокоуровневые задачи по разработке.
⏰ Время прохождения теста ограничено 30 минут
👉 ПРОЙТИ ТЕСТ: https://vk.cc/cJ4GlS
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Дикая Java
«Безопасный язык» говорили они, «четкая спецификация» говорили они, «Java не даст вам выстрелить себе в ногу» и прочее в таком духе. Реальность же оказалась куда веселее официальной документации и мнений экспертов.
«JVM темна и полна ужасов». (ц)
https://habr.com/ru/articles/886080/
👉@BookJava
🧵 Разбираемся с CompletableFuture
в Java
Сегодня я хочу рассказать вам про CompletableFuture
— мощный инструмент для работы с асинхронными операциями в Java. Если вам приходилось ждать выполнения долгих задач в коде и хотелось бы улучшить производительность, то этот пост для вас! 🚀
🔹 Что такое CompletableFuture
?CompletableFuture
— это часть java.util.concurrent
с Java 8, которая позволяет выполнять асинхронные задачи и удобно комбинировать их. В отличие от обычного Future
, CompletableFuture
поддерживает цепочки вызовов, композицию задач и обработку ошибок.
🔹 Пример использования
Допустим, у нас есть сервис, который загружает данные по сети. Обычный подход синхронного вызова будет блокировать поток, но с CompletableFuture
мы можем избежать этого:
import java.util.concurrent.CompletableFuture;
public class CompletableFutureExample {
public static void main(String[] args) {
CompletableFuture.supplyAsync(() -> {
System.out.println("Загружаем данные...");
sleep(2000);
return "Данные загружены";
}).thenApply(data -> {
System.out.println("Обрабатываем: " + data);
return data.toUpperCase();
}).thenAccept(System.out::println)
.exceptionally(ex -> {
System.out.println("Ошибка: " + ex.getMessage());
return null;
});
sleep(3000); // Даем время асинхронной операции завершиться
}
private static void sleep(long millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
supplyAsync()
— запускает асинхронную задачу в отдельном потоке. thenApply()
— позволяет обработать результат (например, изменить его формат). thenAccept()
— принимает готовый результат и выполняет действие. exceptionally()
— обрабатывает возможные ошибки.CompletableFuture
в своих проектах? Делитесь опытом в комментариях! 👇 💥 Apache Kafka: мощь, которой вы еще не владеете! Курс, который сделает вас профи в потоках данных.💥
Превратите свои проекты в образец стабильности и скорости! Учитесь у экспертов, которые знают Kafka изнутри.
На курсе вы научитесь:
- Разворачивать Kafka и настраивать брокеры.
- Использовать API и разрабатывать программы на Kafka Streams, Spring, Akka, ZIO.
- Интегрировать Kafka с другими системами.
- Настроить мониторинг и безопасность.
💼 Реальная практика, живые лекции и диплом, который ценят ведущие компании.
💪 Готовы прокачаться? Пройдите полное тестирование и присоединяйтесь к группе с максимальной скидкой по промокоду "Kafka_5", а также получите доступ к открытым урокам курса: 👉 https://vk.cc/cIX01X
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Абстракция в Java – что это и зачем нужна?
Одна из ключевых концепций ООП – абстракция. Мы постоянно используем её в Java, даже не задумываясь. Но давайте разберёмся, зачем она нужна и как правильно применять.
📌 Что такое абстракция?
Абстракция – это процесс выделения существенных характеристик объекта, скрывая при этом детали реализации. Это позволяет нам работать с объектами через их интерфейсы, а не конкретные реализации.
Пример из жизни:
Когда вы едете на машине, вам не нужно знать, как работает двигатель. Достаточно уметь жать на газ, тормозить и поворачивать руль. Вот это и есть абстракция – вам доступен только необходимый интерфейс, а детали скрыты.
🔹 Как реализуется абстракция в Java?
В Java абстракция достигается двумя способами:
1. Абстрактные классы (abstract
class)
2. Интерфейсы (interface
)
🚀 Абстрактные классы
Абстрактный класс может содержать как реализованные, так и абстрактные (без реализации) методы. Его нельзя создать через new
, он служит основой для дочерних классов.
abstract class Vehicle {
abstract void start(); // абстрактный метод, без реализации
void stop() {
System.out.println("Машина остановилась");
}
}
class Car extends Vehicle {
@Override
void start() {
System.out.println("Запуск двигателя...");
}
}
public class Main {
public static void main(String[] args) {
Vehicle car = new Car();
car.start();
car.stop();
}
}
start()
– это абстрактный метод, его реализация будет в Car
. А вот stop()
реализован в базовом классе.default
и static
методы.
interface Engine {
void start();
}
class ElectricCar implements Engine {
@Override
public void start() {
System.out.println("Электродвигатель включен!");
}
}
🚀 AutoCloseable HttpClient в Java 21 🚀
HttpClient был обновлён и теперь реализует интерфейс AutoCloseable в Java 21. 🔥
👉 @BookJava
Бесплатный вебинар, который поможет начать изучение Spark с нуля!
👨💻🛠👨🏻💻 Кому будет полезно?
- Data-инженерам и аналитикам, работающим с большими объемами данных
- Программистам, переходящим с других технологий обработки данных на Spark
Не пропустите прямой эфир, где мы начнем изучение Big Data фреймворка и подробно разберем обработку графов с помощью Spark:
- ключевые понятия, включая структуру графов, а также алгоритмы, доступные в библиотеках GraphX и GraphFrames
- создание и обработку графов на основе различных типов данных
- эффективную работу с большими графами
- 2 популярных алгоритма для анализа данных: PageRank и Connected Components
- интеграцию графов в проекты
- практические примеры построения графов и их анализ
Все участники вебинара смогут продолжить обучение на курсе «Spark Developer» с выгодной скидкой.
➡️ Регистрация: https://vk.cc/cIVWClРеклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Stream API: Обзор и Основные Методы
Stream API – мощный инструмент для обработки данных. Его основные принципы:
✅ Композиция – построение логики из небольших, независимых и чистых функций.
✅ Single Responsibility – каждый шаг выполняет одну конкретную операцию.
Такой подход обеспечивает:
✔️ Читаемость кода.
✔️ Отсутствие локальных переменных.
✔️ Линейную последовательность действий.
Основные компоненты Stream API
Любой поток состоит из трех ключевых частей:
1️⃣ Источник данных (коллекция, массив, файл и т. д.).
2️⃣ Промежуточные преобразования (filter, map и другие).
3️⃣ Конечная операция (коллекционирование, агрегация, перебор).
Способы создания стрима
Stream можно создать несколькими способами:
🔹 Из коллекции: collection.stream()
🔹 Из массива: Arrays.stream(array)
🔹 Из набора элементов: Stream.of(1, 2, 3)
🔹 Бесконечный поток: Stream.iterate(0, n -> n + 1)
🔹 Бесконечный поток с ограничением (Java 9): Stream.iterate(1, n -> n < 100, n -> n * 2)
🔹 Генерация элементов: Stream.generate(Math::random)
🔹 Диапазон значений:
- IntStream.range(1, 5)
(1, 2, 3, 4)
- IntStream.rangeClosed(1, 5)
(1, 2, 3, 4, 5)
🔹 Из файла: Files.lines(Path.of("file.txt"))
🔹 Из строки: "abc".chars()
Промежуточные операции
Stream API поддерживает множество преобразований. Наиболее распространенные:
✔️ Фильтрация: filter(Predicate<T>)
– оставляет только элементы, соответствующие условию.
✔️ Удаление дубликатов: distinct()
– исключает повторяющиеся элементы.
✔️ Ограничение количества: limit(n)
– берет первые n
элементов.
✔️ Сортировка: sorted()
– упорядочивает элементы.
Менее очевидные операции
🔹 map(Function<T, R>) – применяет функцию к каждому элементу.
🔹 flatMap(Function<T, Stream<R>>) – «разворачивает» элементы из вложенных структур.
🔹 takeWhile(Predicate<T>) (Java 9) – берет элементы, пока выполняется условие.
🔹 dropWhile(Predicate<T>) (Java 9) – пропускает элементы, пока условие выполняется.
🔹 peek(Consumer<T>) – выполняет действие без изменения элементов (удобно для логирования).
Конечные операции
Стрим начинает обработку данных только при вызове конечной операции:
📌 Коллекционирование:
- collect(Collectors.toList())
– собирает в List
.
- collect(Collectors.toSet())
– собирает в Set
.
📌 Поиск элементов:
- findFirst()
– первый элемент.
- findAny()
– любой элемент (оптимизирован для параллельных потоков).
- anyMatch(Predicate<T>)
– хотя бы один элемент удовлетворяет условию.
- allMatch(Predicate<T>)
– все элементы удовлетворяют условию.
- noneMatch(Predicate<T>)
– ни один элемент не удовлетворяет условию.
📌 Агрегация:
- min(Comparator<T>)
– минимальный элемент.
- max(Comparator<T>)
– максимальный элемент.
- count()
– количество элементов.
- reduce(BinaryOperator<T>)
– свертка элементов в одно значение.
📌 Побочные эффекты:
- forEach(Consumer<T>)
– выполняет действие над каждым элементом.
- forEachOrdered(Consumer<T>)
– выполняет действие, сохраняя порядок (важно для параллельных потоков).
Особенности работы со Stream API
1️⃣ Стрим – это не структура данных
Он лишь обходит источник, выполняя операции лениво.
2️⃣ Стрим нельзя использовать повторно
После вызова конечной операции повторное использование потока приведет к IllegalStateException
.
3️⃣ Исходные данные не изменяются
Методы Stream API не модифицируют исходную коллекцию.
Разбор сложных случаев
❌ Ошибочный код:
Stream.of(-1, 0, 1).max(Math::max).get();
max()
принимает Comparator<T>
, но Math.max(a, b)
– это BiFunction<Integer, Integer, Integer>
. Они не эквивалентны!
Stream.of(-1, 0, 1).max(Integer::compareTo).get(); // Вернет 1
🔥 Разбираем CompletableFuture
в Java: Асинхронность без боли
Всем добрый вечер! Сегодня расскажу про CompletableFuture
— мощный инструмент для работы с асинхронными операциями в Java. Если вы хотите избавиться от блокирующего кода и сложных коллбэков, этот пост для вас!
🤔 Что такое CompletableFuture
?
Это часть java.util.concurrent
, позволяющая писать асинхронный код в декларативном стиле, без создания сложных цепочек Thread
и ExecutorService
.
🚀 Базовый пример использования
Допустим, у нас есть задача загрузить данные с сервера. Как это сделать асинхронно?
import java.util.concurrent.CompletableFuture;
public class AsyncExample {
public static void main(String[] args) {
CompletableFuture.supplyAsync(() -> {
// Имитация долгого запроса
sleep(2000);
return "Данные загружены";
}).thenAccept(result ->
System.out.println("Результат: " + result)
);
System.out.println("Задача запущена, ждем результат...");
sleep(3000); // Чтобы main не завершился раньше времени
}
private static void sleep(int millis) {
try { Thread.sleep(millis); }
catch (InterruptedException e) { Thread.currentThread().interrupt(); }
}
}
supplyAsync()
— выполняет операцию в фоновом потоке. thenAccept()
— получает результат и выполняет код после завершения.
CompletableFuture.supplyAsync(() -> "Привет, ")
.thenApply(greeting -> greeting + "мир!")
.thenAccept(System.out::println);
thenApply()
изменяет данные перед следующим шагом. thenAccept()
выполняет финальную операцию. CompletableFuture
? Делитесь опытом в комментариях! 💬📌 Java: Как работает volatile
и когда его использовать?
🔥 Что делает volatile
?
Ключевое слово volatile
гарантирует, что переменная всегда будет читаться из памяти, а не из кэша потока. Это помогает избежать проблем, когда один поток изменяет переменную, но другой поток продолжает работать со старым значением из кэша.
🔄 Разбираем на примере:
class SharedResource {
volatile boolean flag = false;
void changeFlag() {
flag = true;
}
}
class Worker extends Thread {
SharedResource resource;
Worker(SharedResource resource) {
this.resource = resource;
}
public void run() {
while (!resource.flag) {
// Ждём, пока флаг изменится
}
System.out.println("Флаг изменился! Поток завершает работу.");
}
}
public class VolatileExample {
public static void main(String[] args) throws InterruptedException {
SharedResource resource = new SharedResource();
Worker worker = new Worker(resource);
worker.start();
Thread.sleep(1000);
resource.changeFlag(); // Флаг изменится, и поток завершит цикл
worker.join();
}
}
volatile
не делает операции атомарными. Если вам нужна атомарность, используйте synchronized
или Atomic
классы. 👩💻 Создание 2D RPG игры на Java 👩💻
На открытом вебинаре вы создадите свою первую 2D RPG на Java с LibGDX, увидите, как код управляет миром игры, и освоите ключевые принципы программирования.
🗓 26 февраля в 20:00 МСК
🆓 Бесплатно. Урок в рамках старта курса «Java-разработчик».
Это не просто теория — это реальный проект, который поможет вам понять логику Java-разработки и ускорить ваш путь к первому коммерческому коду.
Спикер Александр Фисунов — Senior Kotlin Developer в SSP Software на проекте ВТБ, опытный Java-разработчик и кандидат технических наук.
🔗 Ссылка на регистрацию: https://vk.cc/cINskz
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
⚡️ 5 Фишек Lombok, Которые Вы Должны Знать!
Если вы до сих пор пишете геттеры и сеттеры вручную, самое время это прекратить! 😄
Вот 5 крутых аннотаций, которые обязательно нужно знать:
🔹 @Data
– Комбо-аннотация, которая сразу добавляет @Getter
, @Setter
, @ToString
, @EqualsAndHashCode
и @RequiredArgsConstructor
. Если у вас обычный POJO-класс, просто ставите @Data
, и всё!
@Data
public class User {
private String name;
private int age;
}
@Builder
– Шаблон проектирования "Строитель" на стероидах!
@Builder
public class User {
private String name;
private int age;
}
User user = User.builder().name("Иван").age(25).build();
@Value
– Неперезаписываемые (иммутабельные) объекты. Это как @Data
, но с final
полями и без сеттеров.
@Value
public class User {
String name;
int age;
}
@Slf4j
– Логирование без бойлерплейта.
@Slf4j
public class App {
public static void main(String[] args) {
log.info("Привет, мир!");
}
}
Logger
— Lombok всё сделает за вас. @SneakyThrows
– Скрывает checked
исключения (но осторожно! 😬).
@SneakyThrows
public void readFile(String path) {
Files.readAllLines(Path.of(path));
}
Spring Data JDBC. Проблемы известные, проблемы неизвестные
Михаил Поливаха
Spring Data JDBC — относительно новый модуль Spring Data. У него своя концепция, свои фичи, свои баги и проблемы. Часть этих проблем известна аудитории и описана в документации. Однако иногда документация врет или недоговаривает. К тому же есть некоторые неочевидные детали реализации, которые могут смутить пользователей библиотеки. Это касается многих аспектов — от генерации SQL до маппинга сущностей.
Во время доклада мы посмотрели на ряд подобных сюрпризов, обсудим, баг это или фича и что разработчики планируют с этим делать. Также рассмотрели текущее состояние проекта Spring Data JDBC — над чем идет работа, что исправляется, а что пока нет.
источник
👉@BookJava
🔥 Исключения в Java: что не так с catch (Exception e)
?
Давайте разберем одну из самых частых ошибок, которую я вижу в коде даже опытных Java-программистов. Это перехват всех исключений сразу:
try {
// код, который может выбросить исключение
} catch (Exception e) {
e.printStackTrace();
}
stacktrace
, но не обрабатывать ошибку корректно, это может привести к неожиданным последствиям. Например, приложение продолжит работу в некорректном состоянии. Exception
, мы ловим все исключения, включая RuntimeException
, что делает отладку сложнее. e.printStackTrace()
, пользователь так и не узнает, что пошло не так.
try {
// код
} catch (IOException e) {
log.error("Ошибка ввода-вывода", e);
} catch (NumberFormatException e) {
log.warn("Некорректный формат числа", e);
} catch (Exception e) {
log.error("Непредвиденная ошибка", e);
throw e; // Не глушим ошибку, пробрасываем дальше
}
catch (Exception e)
только если действительно уверены, что вам нужно обработать все возможные ошибки. В остальных случаях — ловите конкретные исключения и работайте с ними правильно! 🚀 catch (Exception e)
? Часто ли видите его в коде? Давайте обсудим в комментариях! 💬📌 Паттерны проектирования: Декоратор в Java
Привет, друзья! Сегодня я хочу разобрать с вами один из самых полезных и часто применяемых паттернов проектирования — Декоратор.
🚀 Когда его использовать?
Когда нужно динамически добавлять функциональность объекту без изменения его кода. Это альтернатива наследованию, но более гибкая и мощная.
🔍 Пример из жизни
Представьте, что у нас есть базовый интерфейс Notifier, который отправляет сообщения. По умолчанию он умеет слать только e-mail уведомления. Но нам нужно добавить поддержку SMS и пуш-уведомлений.
Вместо того чтобы создавать кучу подклассов, мы используем Декоратор:
// Базовый интерфейс
interface Notifier {
void send(String message);
}
// Основная реализация
class EmailNotifier implements Notifier {
@Override
public void send(String message) {
System.out.println("Отправка email: " + message);
}
}
// Базовый декоратор
class NotifierDecorator implements Notifier {
protected Notifier notifier;
public NotifierDecorator(Notifier notifier) {
this.notifier = notifier;
}
@Override
public void send(String message) {
notifier.send(message);
}
}
// Декоратор для SMS
class SMSNotifier extends NotifierDecorator {
public SMSNotifier(Notifier notifier) {
super(notifier);
}
@Override
public void send(String message) {
super.send(message);
System.out.println("Отправка SMS: " + message);
}
}
// Декоратор для Push-уведомлений
class PushNotifier extends NotifierDecorator {
public PushNotifier(Notifier notifier) {
super(notifier);
}
@Override
public void send(String message) {
super.send(message);
System.out.println("Отправка Push-уведомления: " + message);
}
}
// Использование
public class Main {
public static void main(String[] args) {
Notifier notifier = new EmailNotifier();
notifier = new SMSNotifier(notifier);
notifier = new PushNotifier(notifier);
notifier.send("Важное сообщение!");
}
}
Отправка email: Важное сообщение!
Отправка SMS: Важное сообщение!
Отправка Push-уведомления: Важное сообщение!