Библиотека 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
Блокировки в HotSpot JVM

Java Virtual Machine (JVM) — это промежуточное звено между скомпилированным Java-кодом и операционной системой (ОС). Благодаря этому механизму Java-приложения можно запускать на разных платформах без модификаций. Существует множество реализаций JVM, но наиболее популярной является HotSpot, входящая в состав OpenJDK.

Однако JVM не просто транслирует Java-код в инструкции ОС. Она включает в себя множество оптимизаций, позволяющих исполнять код быстрее и эффективнее. Одна из таких оптимизаций касается механизма блокировок (synchronization locks).

Виды блокировок в HotSpot

Виртуальная машина HotSpot использует три вида блокировок в зависимости от уровня конкуренции между потоками:

1️⃣ Fat Lock (Inflated Lock) — классическая блокировка на основе мониторов объектов (mutexes). Этот метод используется, когда большое количество потоков одновременно пытаются захватить блокировку.

2️⃣ Thin Lock (Deflated Lock) — облегчённая блокировка, использующая атомарные CAS-операции (Compare-And-Swap). Такой подход быстрее мьютексов, но становится неэффективным при высоком уровне конкуренции, поскольку требует эксклюзивного доступа.

3️⃣ Biased Lock — предвзятая блокировка, предназначенная для сценариев, в которых объект используется одним и тем же потоком. При первом взаимодействии объект привязывается к потоку, и последующие операции с ним выполняются без затрат на синхронизацию. Однако, если другой поток попытается захватить блокировку, произойдёт глобальная аннулирование (bulk revocation), что может привести к значительным накладным расходам.

> Важно! Biased Lock по умолчанию отключён при запуске JVM, поскольку на старте приложения активно взаимодействуют множество потоков. Через некоторое время он автоматически включается и становится основной стратегией блокировки.

Тонкая настройка JVM
JVM позволяет управлять стратегией блокировок с помощью следующих параметров:

- Отключение Biased Lock

-XX:-UseBiasedLocking

- Регулировка времени включения Biased Lock (по умолчанию 4 сек)

-XX:BiasedLockingStartupDelay=500

Здесь 500 указывает задержку в миллисекундах.

Когда настраивать блокировки вручную?
В большинстве приложений не требуется изменять эти параметры, так как JVM автоматически выбирает оптимальные стратегии. Однако в высоконагруженных сценариях, например в паттерне Producer-Consumer, правильная настройка блокировок может значительно повысить производительность.

Если ваше приложение испытывает проблемы с блокировками, профилирование с помощью JVM TI, JFR (Java Flight Recorder) или perf поможет выявить узкие места и подобрать наиболее подходящий метод синхронизации.

👉@BookJava
👍51👎1
🚀 Разбираемся с var в Java: Когда использовать, а когда нет?

Сегодня разберёмся с var в Java. Этот локальный тип вывода переменной появился в Java 10 и сразу вызвал много споров. Давайте посмотрим, когда его стоит использовать, а когда лучше отказаться.

Когда var полезен?
1️⃣ Сокращение шаблонного кода

var list = new ArrayList<String>(); // читается проще

2️⃣ Улучшает читаемость при длинных объявлениях

var map = new HashMap<String, List<Integer>>();

3️⃣ Хорош при использовании анонимных классов

var thread = new Thread(() -> System.out.println("Hello"));

4️⃣ Идеален для итераторов

for (var entry : map.entrySet()) {
System.out.println(entry.getKey() + " -> " + entry.getValue());
}


Когда var ухудшает код?
1️⃣ Неочевидный тип данных

var data = fetchData(); // Что вернет метод? Интуитивно непонятно!

2️⃣ Снижение читаемости сложного кода

var something = doSomethingComplicated(); // А что это такое?

3️⃣ Не подходит для публичных API
Если метод возвращает var, мы теряем контракт с пользователем API.

🔥 Итог
Используйте var, когда тип очевиден и код становится чище. Не злоупотребляйте им, чтобы не терять читаемость!

📌26 рекомендаций по использованию типа var в Java

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

https://dzone.com/articles/var-work-in-progress

👉@BookJava
👍17👎2👏2
📌 Паттерн "Одиночка" (Singleton) – когда и как правильно использовать?

👋 Сегодня хочу поговорить о Singleton – одном из самых популярных (и часто злоупотребляемых) паттернов в Java.

🔥 Что такое Singleton?
Singleton гарантирует, что у класса будет только один экземпляр и предоставляет глобальную точку доступа к нему.

Пример классического Singleton:

public class Singleton {
private static final Singleton INSTANCE = new Singleton();

private Singleton() {}

public static Singleton getInstance() {
return INSTANCE;
}
}

Здесь используется жадная инициализация – объект создаётся сразу при загрузке класса.

💣 Проблемы Singleton
1️⃣ Нарушение SRP (Single Responsibility Principle) – Singleton управляет своим жизненным циклом.
2️⃣ Проблемы с тестированием – сложность мокирования в юнит-тестах.
3️⃣ Глобальное состояние – сложнее поддерживать код, возможны неожиданные баги.

Когда использовать Singleton?
Если требуется единый точный экземпляр (например, пул соединений, логгер).
Если объект дорого создавать и его состояние неизменно.
Когда глобальная точка доступа действительно оправдана.

🔧 Альтернативы
👉 Dependency Injection (DI) – лучше передавать объект через конструктор.
👉 Enum Singleton – лучший способ создать потокобезопасный Singleton:

public enum SingletonEnum {
INSTANCE;

public void someMethod() {
System.out.println("Работаем!");
}
}

Он защищён от сериализации и reflection-атак! 🚀

👉@BookJava
👍10
🚀 Apache Kafka и Spring — лучшие друзья микросервисов! Хотите узнать, почему?

На открытом уроке мы покажем, как объединить Kafka и Spring Framework для создания масштабируемых и надежных систем. В теории и практике!

🔍 Вы научитесь:
- Настраивать асинхронное взаимодействие
- Обрабатывать сообщения в реальном времени
- Использовать инструменты мониторинга для оптимизации работы микросервисов

🗓 Занятие пройдет 18 февраля в 20:00 МСК и будет приурочено к старту курса «Apache Kafka». После урока вы сможете продолжить обучение по специальной цене и даже в рассрочку!

👉 Забронируйте свое место на открытом уроке! Пройдите короткий тест и получите запись: https://vk.cc/cIGdPJ

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
🚀 5 полезных библиотек для Java-разработчика

🔹 Lombok – убирает бойлерплейт-код. Автоматически генерирует геттеры, сеттеры, конструкторы, toString(), equals(), hashCode(). Больше не нужно писать однотипный код вручную!

🔹 Guava – коллекции, кэширование, строки, примитивные типы, функциональные утилиты и многое другое. Разработана Google, широко используется в индустрии.

🔹 Apache Commons – набор утилит для работы со строками, коллекциями, потоками, датами. Позволяет сократить код и улучшить его читаемость.

🔹 Jackson – одна из лучших библиотек для работы с JSON. Позволяет сериализовать и десериализовать Java-объекты быстро и без лишнего кода.

🔹 Junit + Mockito – тестирование в Java. JUnit – основной инструмент для написания юнит-тестов, а Mockito помогает мокировать зависимости и тестировать сложные сценарии.

👉@BookJava
👍12🔥4😁1
Что спрашивают на собеседовании у Middle Java-разработчика?

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

Интервьюер Илья Аров с опытом работы в крупных банках задаст реальные вопросы разработчику-добровольцу и разберёт его ответы. В конце — время вопросов ментору из зала.

Что узнаешь на эфире:

Какие вопросы задают на собеседованиях и зачем
Как подготовиться, чтобы получить достойный оффер
Чего ждут от кандидатов на Middle Java

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

Реклама. ООО "ШОРТКАТ", ИНН: 9731139396, erid: 2Vtzqw2cVob
💡Совет: по умолчанию ленивую загрузку в @Hibernate можно использовать только для отношений, но не для простых (базовых) атрибутов.

Чтобы она работала и для полей, необходимо использовать байткод-энхансмент через плагин. В этом случае поля, отмеченные как lazy, будут загружаться при первом обращении к ним.

#Java #JPA

👉@BookJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Работа с временными метками в Java: что нужно знать?

Всем раннего утра! 👋 Сегодня разберём важную тему — работу с временными метками в Java. Это может пригодиться при логировании, кэшировании, обработке данных и даже в повседневных задачах.

1. Получение текущей временной метки
В Java с появлением java.time всё стало проще. Самый удобный способ получить timestamp:

Instant instant = Instant.now();
long timestamp = instant.toEpochMilli(); // В миллисекундах

Значение timestamp соответствует количеству миллисекунд, прошедших с 1 января 1970 года (UTC).

2. Преобразование timestamp в дату и время
Допустим, у нас есть временная метка, и нам нужно преобразовать её в локальное время:

long timestamp = 1700000000000L; // Пример временной метки
Instant instant = Instant.ofEpochMilli(timestamp);
ZonedDateTime dateTime = instant.atZone(ZoneId.systemDefault());
System.out.println(dateTime);

Так можно легко получить читабельную дату.

3. Разница между датами
Вычислить разницу между двумя временными метками можно так:

Instant start = Instant.now();
Thread.sleep(2000); // Эмуляция задержки
Instant end = Instant.now();

Duration duration = Duration.between(start, end);
System.out.println("Разница в секундах: " + duration.getSeconds());

Отличный способ измерять производительность кода!

4. Форматирование и вывод даты
Для вывода даты в удобочитаемом формате используем DateTimeFormatter:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss");
String formatted = dateTime.format(formatter);
System.out.println(formatted);


Итог
Работа с временными метками в Java теперь проще, чем когда-либо. Используйте Instant, Duration и DateTimeFormatter для удобного управления временем.

👉@BookJava
🎉5👍4
А всё, а раньше надо было!

Именно это скажут вам потерянные данные, когда из Кафки они превратятся в кашку. Лучше разбираться в инструменте до того, как начнёшь с ним работать по-серьёзному — не только в теории, но и на практике.

Пока все данные на месте, приходите на «Apache Kafka для разработчиков»:

➡️ Разберётесь в основах Kafka, её архитектуре и бизнес-процессах.
➡️ Научитесь работать с системами, передающими и получающими большие объёмы сообщений.
➡️ Подготовитесь к базовым собеседованиям на позиции, связанные с Kafka.

Углубленный курс с практикой на Java, Docker и Postgres.

▶️Занять место — по ссылке 

#реклама
О рекламодателе
👍3
📌 Паттерны проектирования: Декоратор в 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-уведомления: Важное сообщение!


Преимущества:
✔️ Гибкость: можно комбинировать декораторы в любом порядке
✔️ Принцип открытости/закрытости (OCP) — код легко расширяется
✔️ Разделение обязанностей — каждая часть отвечает за свою функцию

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

👉@BookJava
👍7
👩‍💻 Resilience4j. RateLimiter

Приглашаем на открытый урок.

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

Где мы разберем:

✔️Что такое RateLimiter?
✔️Настройка и особенности.

Урок будет полезен тем, кто хочет:
✔️Защитить приложения от пиковых нагрузок и обеспечить высокую доступность.
✔️Использовать ключевые инструменты Resilience4j для управления трафиком.
✔️Глубже понять, как писать надёжные микросервисы и оптимизировать их под реальные сценарии.

В результате урока вы:
✔️Разберётесь, как работает RateLimiter и в чём его польза при ограничении запросов.
✔️Получите несколько примеров настройки и сможете применять эти приёмы в базовых сценариях.

Спикер Сергей Петрелевич — опытный Java/Kotlin-разработчик и преподаватель.

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

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3
🔥 Исключения в Java: что не так с catch (Exception e)?

Давайте разберем одну из самых частых ошибок, которую я вижу в коде даже опытных Java-программистов. Это перехват всех исключений сразу:


try {
// код, который может выбросить исключение
} catch (Exception e) {
e.printStackTrace();
}


📌 В чем проблема?
1️⃣ Глушение ошибок – если просто печатать stacktrace, но не обрабатывать ошибку корректно, это может привести к неожиданным последствиям. Например, приложение продолжит работу в некорректном состоянии.
2️⃣ Ловим слишком много – перехватывая Exception, мы ловим все исключения, включая RuntimeException, что делает отладку сложнее.
3️⃣ Скрытые ошибки – если в коде, например, ошибка валидации и мы просто пишем 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)? Часто ли видите его в коде? Давайте обсудим в комментариях! 💬

👉@BookJava
👍6👎1
⚔️Ваши микросервисы не дружат между собой?

Сначала один сервис завис, потом второй, а в логах — хаос. Конфиги разбросаны по разным файлам, API ломаются после каждого релиза, а тестировщики смотрят на вас как на главного злодея проекта.

👩‍💻 Есть способ навести порядок. Spring Cloud помогает микросервисам работать как единая система: управлять конфигурациями, находить друг друга без лишних костылей и не падать при каждом обновлении.

🦾Разберём, как это сделать, на открытом уроке «Экосистема Spring Cloud».

Когда: 25 февраля в 20:00 (мск).

Вы узнаете, как использовать Service Discovery, API Gateway и Config Server. А еще получите скидку на большое обучение «Java Developer. Advanced».

Не ждите, пока сервисы начнут воевать друг с другом.

🔗 Регистрируйтесь прямо сейчас: https://vk.cc/cIL61o

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2👏1
Media is too big
VIEW IN TELEGRAM
Spring Data JDBC. Проблемы известные, проблемы неизвестные
Михаил Поливаха

Spring Data JDBC — относительно новый модуль Spring Data. У него своя концепция, свои фичи, свои баги и проблемы. Часть этих проблем известна аудитории и описана в документации. Однако иногда документация врет или недоговаривает. К тому же есть некоторые неочевидные детали реализации, которые могут смутить пользователей библиотеки. Это касается многих аспектов — от генерации SQL до маппинга сущностей.

Во время доклада мы посмотрели на ряд подобных сюрпризов, обсудим, баг это или фича и что разработчики планируют с этим делать. Также рассмотрели текущее состояние проекта Spring Data JDBC — над чем идет работа, что исправляется, а что пока нет.

источник

👉@BookJava
👍7
Please open Telegram to view this post
VIEW IN TELEGRAM
🤡10🥰1💩1
⚡️ 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;
}

📌 Отлично подходит для DTO!

🔹 @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));
}

📌 Работает так, как будто исключений нет, но лучше использовать осознанно!

👉 Используете Lombok в проектах? Какая аннотация вам больше всего нравится? Делитесь в комментариях! 💬

👉@BookJava
👍14
🚀 Разбираемся с Optional в Java: избегаем NullPointerException!

Привет, друзья! Сегодня хочу поговорить о Optional, который помогает нам избежать NullPointerException и делает код чище.

Что такое Optional?
Optional<T> — это контейнер, который может содержать значение типа T или быть пустым. Это альтернатива null, которая явно указывает, что значение может отсутствовать.

🔥 Как использовать?
1️⃣ Создание Optional:

Optional<String> optional = Optional.of("Hello, Java!");

⚠️ Если передать null, будет NullPointerException.

2️⃣ Создание пустого Optional:

Optional<String> emptyOptional = Optional.empty();


3️⃣ Обёртка для возможного null:

Optional<String> nullableOptional = Optional.ofNullable(null);

Если передать null, Optional не упадёт, а просто будет пустым.

4️⃣ Проверка наличия значения:

optional.isPresent(); // true
optional.isEmpty(); // false

Но лучше использовать ifPresent:

optional.ifPresent(value -> System.out.println(value));


5️⃣ Получение значения с orElse:

String result = optional.orElse("Значение по умолчанию");


6️⃣ Получение с orElseGet:

String result = optional.orElseGet(() -> "Вычисленное значение");


7️⃣ Исключение, если значения нет:

String result = optional.orElseThrow(() -> new RuntimeException("Значение отсутствует!"));


8️⃣ Фильтрация:

Optional<String> filtered = optional.filter(val -> val.startsWith("Hello"));


9️⃣ Трансформация с map:

Optional<Integer> length = optional.map(String::length);


🔚 Итог:
Optional — мощный инструмент, но не стоит злоупотреблять им везде. Используйте его в возвращаемых значениях, но не в полях и параметрах методов.

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

👉@BookJava
👍11
👩‍💻 Создание 2D RPG игры на Java 👩‍💻

На открытом вебинаре вы создадите свою первую 2D RPG на Java с LibGDX, увидите, как код управляет миром игры, и освоите ключевые принципы программирования.

🗓 26 февраля в 20:00 МСК
🆓 Бесплатно. Урок в рамках старта курса «Java-разработчик».

Это не просто теория — это реальный проект, который поможет вам понять логику Java-разработки и ускорить ваш путь к первому коммерческому коду.

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

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

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
👏2👍1🎉1
В чем разница между Iterator и ListIterator?

— Iterator может итерироваться только вперед, а ListIterator может и вперед и назад.

— ListIterator имеет дополнительные методы previous(), hasPrevious(), add(), set().

— ListIterator позволяет получить индекс текущего элемента.

— ListIterator может начать итерацию с произвольного индекса списка, а Iterator только с начала.

— ListIterator можно получить только из объектов, реализующих List, а Iterator из любой коллекции.

— ListIterator является более функциональным и позволяет вносить изменения в список во время итерации, Iterator — только читать.

— Итераторы безопасны для использования в многопоточных приложениях, а ListIterator — нет.

👉@BookJava
👍7🥰4
📌 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 классы.
Он не предотвращает гонки данных, но гарантирует видимость изменений между потоками.
Лучше всего подходит для флагов завершения потоков и подобных сценариев.

👉@BookJava
👍6