Библиотека Java разработчика
10.8K subscribers
1.14K photos
564 videos
58 files
1.44K links
📚 Лайфхаки, приёмы и лучшие практики для Java-разработчиков. Всё, что ускорит код и прокачает навыки. Java, Spring, Maven, Hibernate.


По всем вопросам @evgenycarter

РКН clck.ru/3KoGeP
Download Telegram
👩‍💻 Вы — 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
Please open Telegram to view this post
VIEW IN TELEGRAM
🧵 Разбираемся с 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();
}
}
}


🔹 Разбор кода
1️⃣ supplyAsync() — запускает асинхронную задачу в отдельном потоке.
2️⃣ thenApply() — позволяет обработать результат (например, изменить его формат).
3️⃣ thenAccept() — принимает готовый результат и выполняет действие.
4️⃣ exceptionally() — обрабатывает возможные ошибки.

🔹 Зачем это нужно?
Улучшает производительность за счет асинхронного выполнения.
Избегает блокировки основного потока.
Позволяет легко комбинировать операции.

Используете ли вы CompletableFuture в своих проектах? Делитесь опытом в комментариях! 👇

👉@BookJava
👍61
⚡️ Квиз на знание Java

Пройти тестирование — сложно! А ты справишься?
22 вопроса, 30 минут

Проверь себя - пройди квиз и оцени свой уровень навыков, а также свою готовность к обучению на курсе — «Java Developer. Advanced» от Отус.

👩‍💻 На курсе ты научишься профилировать приложения, настраивать GC, работать с реактивными подходами и мониторить метрики в Grafana. Пройдешь весь путь от JVM до Kubernetes, научишься анализировать «горячие точки», оптимизировать приложения и настраивать интеграции с Prometheus.

➡️ ПРОЙТИ ТЕСТ: https://vk.cc/cIZDax

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM
1
Дикая Java

«Безопасный язык» говорили они, «четкая спецификация» говорили они, «Java не даст вам выстрелить себе в ногу» и прочее в таком духе. Реальность же оказалась куда веселее официальной документации и мнений экспертов.

«JVM темна и полна ужасов». (ц)

https://habr.com/ru/articles/886080/

👉@BookJava
👍4
🚀 Используем Optional правильно в Java

Сегодня разберем Optional – мощный инструмент, который помогает избежать NullPointerException. Но многие используют его неправильно! Давайте посмотрим, как его применять эффективно.

Как делать НЕ надо:

Optional<String> optional = Optional.ofNullable(getValue());
if (optional.isPresent()) {
System.out.println(optional.get());
}

Почему плохо?
- get() без проверки – потенциальная ловушка.
- Лишний if – можно сделать проще.

Как надо:

Optional.ofNullable(getValue()).ifPresent(System.out::println);

или, если нужно значение по умолчанию:

String value = Optional.ofNullable(getValue()).orElse("Default Value");

Крутые приемы с Optional:
orElseGet – лениво вычисляет значение
orElseThrow – выбрасывает исключение, если Optional пуст
map и flatMap – позволяют трансформировать данные

🔥 Советы:
1️⃣ Не используйте Optional для полей классов – это не сериализуемо.
2️⃣ Не передавайте Optional в аргументах методов – это антипаттерн.
3️⃣ Optional хорош для возвращаемых значений – используйте его вместо null.

Как вы используете Optional в своих проектах? Делитесь в комментариях!

👉@BookJava
👍5
🦾👩‍💻Хардкорный тест по языку Java👩‍💻🦾

👩‍💻 Пройдите тест из 21 вопроса и проверьте, насколько вы готовы к обучению на углубленном курсе «Разработчик на Spring Framework» от OTUS.
Сможете сдать - пройдете на курс по спеццене!

💻 За 5 месяцев обучения вы освоите современные возможности Spring, научитесь быстро проходить путь от идеи до production-grade, создавать Web-приложения на микросервисной архитектуре и решать высокоуровневые задачи по разработке.

Время прохождения теста ограничено 30 минут

👉 ПРОЙТИ ТЕСТ: https://vk.cc/cJ4GlS

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM
Используем 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());


На что обратить внимание?
1️⃣ @Slf4j использует SLF4J API, поэтому вам все равно потребуется подключить реализацию логирования, например Logback:


<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.11</version>
</dependency>


2️⃣ Если нужен другой логгер, можно использовать альтернативные аннотации:
- @Log — для java.util.logging
- @Log4j — для Apache Log4j
- @Log4j2 — для Log4j2

3️⃣ Не забывайте про уровень логирования!
Используйте debug для отладки, info для полезных сообщений, warn для предупреждений и error для ошибок.

Вывод: @Slf4j — это удобный инструмент, который избавляет от лишнего кода и упрощает работу с логированием. Если вы еще не используете Lombok для логирования, самое время попробовать!

👉@BookJava
👍10
⚡️ Кастомный toString() в Java – как сделать правильно?

Сегодня поговорим про метод toString() в Java. Казалось бы, мелочь, но грамотная реализация этого метода значительно упрощает отладку и логирование.

Как делать НЕ стоит
Обычная ошибка – использовать toString() по умолчанию или писать его вручную без четкой структуры:


public class User {
private String name;
private int age;

// Ошибочный вариант
@Override
public String toString() {
return "User[name=" + name + ", age=" + age + "]";
}
}

Минусы такого подхода:
- Код громоздкий и трудно читаемый
- При добавлении новых полей легко забыть их добавить в toString()
- Нет удобного форматирования

Как делать правильно
Лучший вариант – использовать String.format() или StringJoiner, но ещё лучше – библиотеку Lombok или Objects.toString():


import lombok.ToString;

@ToString
public class User {
private String name;
private int age;
}


Или без Lombok, но читабельно:


import java.util.Objects;

public class User {
private String name;
private int age;

@Override
public String toString() {
return String.format("User{name='%s', age=%d}", name, age);
}
}

Плюсы:
- Автоматически форматируется
- Читаемый и поддерживаемый код
- Легко расширять

Используйте toString() осознанно, и ваш код станет лучше! Какой способ используете вы?

👉@BookJava
👎41👍1
Утренний рефакторинг с Дженной Ортегой*

На относительно простом примере показываю как можно сделать программу «снова великой». Ключевые стадии рефакторинга, Java, эмулятор и Jenna Ortega в нейросетевом исполнении.

https://habr.com/ru/articles/886890/

👉@BookJava
👍2
🔍Что спрашивают на собеседовании у Middle Java-разработчика

Уже завтра, 5 марта в 19:00 мск — бесплатное открытое собеседование в прямом эфире!

Интервьюер Алексей Ушаровский (Oracle, Сбер) задаст реальные вопросы разработчику-добровольцу и разберёт его ответы. В конце — время вопросов ментору из зала.

Что узнаешь на эфире:
📂 Какие вопросы задают на собеседованиях и зачем

📂 Как подготовиться, чтобы получить достойный оффер

📂 Чего ждут от кандидатов на Middle Java

Запишись на эфир в боте ШОРТКАТ → @shortcut_sh_bot

Реклама. ООО "ШОРТКАТ", ИНН: 9731139396, erid: 2VtzqxddYrJ
Please open Telegram to view this post
VIEW IN TELEGRAM
1
🔥 Почему Optional в Java – не просто контейнер!

Сегодня разберём важную тему: Optional в Java – это не просто удобный способ избежать null, но и мощный инструмент для работы с потоками данных.

🚀 Как правильно использовать Optional?

1️⃣ Избегаем null-чеков
Раньше код был полон if (obj != null), но теперь:

Optional<String> name = Optional.ofNullable(user.getName());
name.ifPresent(System.out::println);

Это делает код чище и понятнее.

2️⃣ Комбинируем с map() и flatMap()
Если у нас есть объект, внутри которого другой объект, а внутри него – ещё один, Optional поможет избежать вложенных if-else:

Optional<String> city = Optional.ofNullable(user)
.map(User::getAddress)
.map(Address::getCity);

Всё элегантно и лаконично!

3️⃣ Используем orElse() и orElseGet() правильно
Антипаттерн – всегда выполняет new Object():

User user = optionalUser.orElse(new User());

Лучше такorElseGet() вызовется только если optionalUser пуст:

User user = optionalUser.orElseGet(User::new);

Это особенно важно, если объект тяжёлый в создании.

4️⃣ orElseThrow() – избавляемся от null вообще
Когда отсутствие значения – это ошибка, не бойтесь выбрасывать исключение:

User user = optionalUser.orElseThrow(() -> new RuntimeException("User not found"));

Это делает код безопаснее!

Когда не стоит использовать Optional?
- В полях сущностей (например, JPA) – это может ухудшить производительность.
- Для коллекций – лучше возвращать пустую коллекцию, а не Optional<List<T>>.

А как ты используешь Optional в своём коде? Делись в комментариях! 👇

👉@BookJava
👍8
⁉️ По-прежнему перебираете списки с for и while? Код превращается в кашу из циклов и условий?

Оптимизация занимает больше времени, чем сам проект?

👩‍💻 Stream API — мощный инструмент, который позволит вам писать элегантный, лаконичный и производительный код.

⚡️ На открытом вебинаре 13 марта в 20:00 мск разберём ключевые операции Stream API, научимся фильтровать, группировать и трансформировать данные в несколько строк кода.

🎙 Спикер Александр Фисунов — Senior Kotlin Developer в SSP Software на проекте ВТБ, опытный Java-разработчик и кандидат технических наук.

Участники вебинара получат скидку для обучение на курсе «Java-разработчик»

🔗 Ссылка на регистрацию: https://vk.cc/cJjAao

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM
🏆 5 ЗОЛОТЫХ ПРАВИЛ ЧИСТОГО КОДА В JAVA

1️⃣ Понятные названия
Используйте осмысленные имена для переменных, методов и классов. Название должно отвечать на вопрос "Что делает этот код?" без необходимости заглядывать внутрь.
int a = 5;
int maxRetries = 5;

2️⃣ Короткие методы
Огромные методы с кучей логики сложно читать и поддерживать. Разбивайте их на мелкие, понятные части. Хороший метод делает только одну вещь и делает её хорошо.

3️⃣ Минимум вложенности
Чем больше if-else и циклов внутри друг друга — тем сложнее понимать код. Используйте ранний выход (return, continue, break), чтобы уменьшить вложенность.

4️⃣ Избегайте магических чисел
Никогда не вставляйте числа или строки прямо в код. Заводите константы.
if (status == 3) {...}
if (status == ORDER_COMPLETED) {...}

5️⃣ Отказ от комментариев в пользу читаемого кода
Комментарий не должен объяснять что делает код — это обязанность самого кода! Если без комментариев неясно, что происходит, значит, нужно переписать код.

👉 Какое из этих правил вы чаще всего нарушаете? Или, может, у вас есть своё золотое правило чистого кода? Пишите в комментариях!

👉@BookJava
👍13👎1
Совет по Spring Boot 💡

Если вы используете DTO в Spring Data/JPA, вы можете автоматизировать отображение между сущностями и DTO с помощью библиотеки Blaze Persistence (https://persistence.blazebit.com). Тогда вы сможете воспользоваться преимуществами, например, паттерна Spring repository.

👉@BookJava
👍3
⚖️ 👩‍💻 Сравнение механизмов синхронизации потоков с помощью JMH

Понимание синхронизации — ключ к многопоточности. Оцените эффективность механизмов и проверьте гипотезы с помощью JMH.

🗓 13 марта в 20:00 МСК
🆓 Бесплатно. Урок в рамках старта курса «Java Developer. Advanced».

📌О чём поговорим:
- Ключевые механизмы синхронизации в Java (synchronized, ReentrantLock и другие).
- Особенности их применения в многопоточном коде и влияние на производительность.
- Настройка и проведение бенчмарков JMH для объективного сравнения различных подходов.

📌Кому будет интересно:
Java-разработчикам, инженерам по производительности и любителям многопоточности, желающим оценить скорость и надёжность разных механизмов.

📌В результате урока вы получите:
- Навык реализации JMH-бенчмарков для сравнения различных инструментов синхронизации.
- Понимание разницы в скорости работы механизмов и уверенность в выборе оптимального решения.

🔗 Ссылка на регистрацию: https://vk.cc/cJlnn7

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM
📌 Spring Boot: Как использовать @Async и не напороться на проблемы?

Сегодня я расскажу вам, как правильно использовать аннотацию @Async в Spring Boot, чтобы асинхронные задачи работали стабильно и без неожиданностей.

🔹 Что делает @Async?

Эта аннотация позволяет выполнять методы в отдельном потоке, не блокируя основной поток приложения. Это удобно, когда нужно, например, отправить email или выполнить сложный расчет без задержки ответа пользователю.

🔹 Как правильно использовать?

1️⃣ Включите поддержку асинхронности
Добавьте в главный класс Spring Boot:

@EnableAsync
@SpringBootApplication
public class MyApplication {
}


2️⃣ Аннотируйте метод в сервисе

@Service
public class EmailService {

@Async
public void sendEmail(String email) {
System.out.println("Отправка email: " + email + " в потоке " + Thread.currentThread().getName());
}
}


3️⃣ Вызывайте метод асинхронно

@Component
public class NotificationSender {

private final EmailService emailService;

public NotificationSender(EmailService emailService) {
this.emailService = emailService;
}

public void notifyUser(String email) {
emailService.sendEmail(email);
System.out.println("Метод notifyUser выполняется в потоке " + Thread.currentThread().getName());
}
}


🔹 Частые ошибки и их решения

Вызываете асинхронный метод внутри того же класса?
Spring не будет проксировать вызов, и @Async просто не сработает. Выносите метод в отдельный бин!

Нет пула потоков?
По умолчанию Spring использует SimpleAsyncTaskExecutor, который создает новый поток для каждой задачи. Это может перегрузить систему. Лучше явно указать пул:

@Configuration
@EnableAsync
public class AsyncConfig {

@Bean
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(100);
executor.initialize();
return executor;
}
}


💡 Вы используете @Async в своем проекте? Какие были подводные камни? Делитесь в комментариях!

👉@BookJava
👍71
⚡️ Квиз на знание Java

Пройти тестирование — сложно! А ты справишься?
21 вопрос, 30 минут

Проверь себя - пройди квиз и оцени свой уровень навыков, а также свою готовность к обучению на курсе — «Разработчик на Spring Framework» от OTUS.

💻 За 5 месяцев обучения ты освоишь современные возможности Spring, научишься быстро проходить путь от идеи до production-grade, создавать Web-приложения на микросервисной архитектуре и решать высокоуровневые задачи по разработке.

👉 ПРОЙТИ ТЕСТ: https://vk.cc/cJotoa

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
🚀 Пишем эффективные SQL-запросы в Hibernate: ТОП ошибок и их исправление

Сегодня поговорим о распространенных ошибках при работе с Hibernate и SQL-запросами. Многие из них приводят к проблемам с производительностью, искаженными данными и даже утечкам памяти.

Ошибка №1: Избыточные запросы (N+1 Problem)
_Проблема:_ Если загружать список сущностей и затем получать связанные данные в цикле, Hibernate будет делать отдельный SQL-запрос для каждой записи.
_Пример:_

List<User> users = session.createQuery("FROM User", User.class).getResultList();
for (User user : users) {
System.out.println(user.getOrders().size()); // Генерирует N дополнительных запросов!
}

Решение: Используйте JOIN FETCH для загрузки связанных данных одним запросом:

List<User> users = session.createQuery(
"SELECT u FROM User u JOIN FETCH u.orders", User.class).getResultList();




Ошибка №2: Использование LIKE без индексов
_Проблема:_ Запросы вида LIKE '%value%' приводят к полному сканированию таблицы, что критично для больших баз данных.
_Пример:_

SELECT * FROM users WHERE username LIKE '%john%';

Решение:
1. Используйте полнотекстовый поиск (например, PostgreSQL full-text search или **Elasticsearch**).
2. Если всё же нужен LIKE, постарайтесь использовать его в виде value%, чтобы индексы работали.



Ошибка №3: Неиспользование batch_size для @OneToMany
_Проблема:_ Если у вас коллекция @OneToMany, Hibernate может загружать каждый элемент отдельным запросом.
Решение: Включаем batch_size, чтобы загружать данные пакетами:

@OneToMany(mappedBy = "user")
@BatchSize(size = 10)
private List<Order> orders;

Либо добавляем глобально в hibernate.cfg.xml:

<property name="hibernate.default_batch_fetch_size">10</property>




Ошибка №4: Неограниченный размер выборки (LIMIT отсутствует)
_Проблема:_ Запрос без LIMIT может возвращать тысячи строк, нагружая базу и приложение.
Решение: Всегда указываем LIMIT или используем setMaxResults():

Query<User> query = session.createQuery("FROM User", User.class);
query.setMaxResults(50); // Ограничиваем выборку
List<User> users = query.getResultList();




🏆 Вывод
Проблемы с Hibernate и SQL встречаются часто, но их можно легко избежать! Следите за запросами и используйте JOIN FETCH, индексы, batch_size и LIMIT, чтобы повысить производительность.

А какие проблемы с Hibernate встречались вам? Делитесь в комментариях! 👇

👉@BookJava
👍6
🔥 Stream API: Фильтрация, Преобразование и Сортировка 🔥

Сегодня я покажу вам, как эффективно работать с Stream API в Java, выполняя фильтрацию, преобразование и сортировку данных.

Допустим, у нас есть список пользователей:


class User {
String name;
int age;

User(String name, int age) {
this.name = name;
this.age = age;
}

@Override
public String toString() {
return name + " (" + age + ")";
}
}


Теперь представьте, что у нас есть список пользователей, и мы хотим:
Оставить только совершеннолетних
Отсортировать их по возрасту
Преобразовать в список имен

Легко справимся с этим с помощью Stream API:


List<User> users = List.of(
new User("Алекс", 25),
new User("Мария", 17),
new User("Иван", 30),
new User("Ольга", 20)
);

List<String> adultNames = users.stream()
.filter(user -> user.age >= 18) // Фильтрация
.sorted(Comparator.comparingInt(user -> user.age)) // Сортировка
.map(user -> user.name) // Преобразование
.toList();

System.out.println(adultNames); // [Ольга, Алекс, Иван]


Что здесь происходит?
🔹 filter(user -> user.age >= 18): Убираем несовершеннолетних.
🔹 sorted(Comparator.comparingInt(user -> user.age)): Сортируем по возрасту.
🔹 map(user -> user.name): Преобразуем User в String, оставляя только имена.
🔹 toList(): Собираем результат в список.

Stream API позволяет писать чистый, читаемый и декларативный код, избавляя от лишних циклов.

А вы активно используете Stream API в своих проектах? Делитесь в комментариях! 🚀

👉@BookJava
👍10
👩‍💻 Открытый урок «Spring Boot: разбор (не)стандартных вопросов интервью»

🗓 17 марта в 20:00 МСК
🆓 Бесплатно. Урок в рамках старта курса «Разработчик на Spring Framework»

Продолжаем готовится к возможному собеседованию.
На уроке мы обсудим вопросы, которые могут встретиться на интервью по теме разработки на Spring.
На очереди Spring Boot.
Подключайтесь.

🔗 Ссылка на регистрацию: https://vk.cc/cJBl4X

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM