bookjava | Unsorted

Telegram-канал bookjava - Библиотека Java разработчика

10986

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

Subscribe to a channel

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

А всё, а раньше надо было!

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

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

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

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

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

#реклама
О рекламодателе

Читать полностью…

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

💡Совет: по умолчанию ленивую загрузку в @Hibernate можно использовать только для отношений, но не для простых (базовых) атрибутов.

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

#Java #JPA

👉@BookJava

Читать полностью…

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

Костыль в JDK и сортировка списков

Говорить об архитектуре и разработке приятно, но ещё полезнее разбирать конкретные примеры. Давайте рассмотрим метод сортировки в Java и разберёмся, почему он устроен именно так.

Если задать вопрос питонисту, он без колебаний выберет list.sort(), ведь в Python это стандартный метод списка. В Java ситуация иная.

Класс Integer реализует интерфейс Comparable, и сортировка чисел — базовая операция для любого языка программирования. Логично было бы ожидать метод sort() в List, но его там нет. Вместо этого есть:


void sort(Comparator<? super E> c) { ... }


Чтобы просто отсортировать список чисел, приходится писать:


list.sort(Comparator.naturalOrder());


На первый взгляд, это выглядит как костыль. Под капотом Comparator.naturalOrder() тривиален:


(c1, c2) -> c1.compareTo(c2)


Так почему же нельзя просто вызвать list.sort() без компаратора? Разбираемся!

Обратная совместимость — главная ценность Java

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


Collections.sort(List<T> list)


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


CustomList sorted = list.sort();


Со временем стало очевидно, что экземплярные методы сортировки удобнее. Однако просто добавить default void sort() в List нельзя.

Проблема с существующими реализациями

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


public class CustomList implements List<T> {
public CustomList sort() { ... }
}


Если бы в Java 8 добавили:


default void sort() { ... }


то компилятор не смог бы корректно обработать конфликт сигнатур (CustomList.sort() возвращает CustomList, а List.sort()void`). Код, использующий `CustomList, перестал бы компилироваться. В результате многие проекты получили бы неожиданные проблемы, а пользователи — головную боль.

Чтобы избежать этого, разработчики JDK не добавили sort() в List, а оставили только sort(Comparator), так как он использовался редко.

Stream API и Kotlin

В Stream API нет таких проблем с совместимостью, поэтому для стримов есть метод:


list = list.stream().sorted().toList();


А в Kotlin вообще есть удобный метод sorted(), соответствующий функциональному стилю.

Как правильно сортировать список в Java

Теперь можно ответить на главный вопрос:

list.sort(Comparator.naturalOrder());
list = list.stream().sorted().toList();

Если вам нравится list.sort(), значит у вас хороший вкус на API. К сожалению, у Java свои исторические особенности, поэтому этот метод отсутствует в JDK.

👉@BookJava

Читать полностью…

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

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

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

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

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

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

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576

Читать полностью…

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

🚀 Разбираемся с 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

Читать полностью…

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

Совет Spring Framework💡

Вы можете автосопрягать несколько бинов, реализующих определенный интерфейс, в список, содержащий все реализации. Определите список с общим типом, который вы хотите использовать. Вы можете использовать инъекцию конструктора, как показано на картинке, или инъекцию поля.

👉@BookJava

Читать полностью…

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

📌 Record vs Class в Java – когда что использовать?

👋 Сегодня разберёмся с record и class в Java. Когда лучше использовать record, а когда стоит остаться на классах?

🧐 Что такое record?
Record — это специальный тип класса, предназначенный для хранения неизменяемых данных. Он автоматически генерирует:
✅ Конструктор, принимающий все поля
toString(), equals(), hashCode()
✅ Методы доступа (`getter'ы`)

📌 Пример использования Record:


public record User(String name, int age) {}

🔥 Это равнозначно следующему классу:

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

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

public String name() { return name; }
public int age() { return age; }

@Override
public boolean equals(Object o) { /* реализация */ }
@Override
public int hashCode() { /* реализация */ }
@Override
public String toString() { /* реализация */ }
}


🏆 Когда использовать record?
✔️ Когда у вас неизменяемые (immutable) объекты
✔️ Когда вам нужны только данные без логики
✔️ Когда хочется избежать бойлерплейта

⛔ Когда НЕ стоит использовать record?
🚫 Если нужно наследование (record не поддерживает `extends`)
🚫 Если объект должен быть мутабельным (изменяемым)
🚫 Если в классе должна быть сложная логика поведения

✍️ Итог
Используйте record, если вам нужен простой DTO (Data Transfer Object) без лишнего кода. Но если у объекта есть логика, стоит оставить класс.

👉@BookJava

Читать полностью…

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

🚀 Stream API в Java: 5 мощных трюков, которые ты мог не знать

Stream API – одна из самых крутых фич в Java, но многие используют только map(), filter() и collect(). Давай разберем 5 полезных трюков, которые сделают код элегантнее и эффективнее!

🔹 1. Группировка элементов (Collectors.groupingBy)
Разбиваем список строк на группы по длине:


List<String> words = List.of("apple", "banana", "cat", "dog", "elephant");
Map<Integer, List<String>> grouped = words.stream()
.collect(Collectors.groupingBy(String::length));

System.out.println(grouped);
// {3=[cat, dog], 5=[apple], 6=[banana], 8=[elephant]}


🔹 2. Уникальные элементы (distinct())
Фильтруем дубликаты в потоке:


List<Integer> numbers = List.of(1, 2, 2, 3, 4, 4, 5);
List<Integer> unique = numbers.stream()
.distinct()
.collect(Collectors.toList());

System.out.println(unique); // [1, 2, 3, 4, 5]


🔹 3. Пропуск N элементов (skip(n))
Хотим пропустить первые 3 элемента и взять только оставшиеся:


List<String> names = List.of("Alice", "Bob", "Charlie", "David", "Eve");
List<String> skipped = names.stream()
.skip(3)
.collect(Collectors.toList());

System.out.println(skipped); // [David, Eve]


🔹 4. Найти максимальное значение (max())
Допустим, у нас есть список чисел, найдем максимальное:


List<Integer> nums = List.of(10, 20, 30, 5, 15);
Optional<Integer> maxNum = nums.stream().max(Integer::compareTo);

maxNum.ifPresent(System.out::println); // 30


🔹 5. Проверить, содержит ли список нужное значение (anyMatch())
Допустим, нам нужно проверить, есть ли в списке число больше 100:


List<Integer> nums = List.of(10, 50, 200, 30);
boolean hasLargeNumber = nums.stream().anyMatch(n -> n > 100);

System.out.println(hasLargeNumber); // true


🔥 Stream API – это мощный инструмент для работы с коллекциями. Используйте его, и ваш код станет чище, короче и быстрее!

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

👉@BookJava

Читать полностью…

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

2️⃣ Что нового в Java 21? ТОП-5 фич, которые стоит знать

Java 21 – это LTS-релиз, который принесёт важные улучшения. Вот самые интересные новинки:

1️⃣ Виртуальные потоки (Virtual Threads) 🧵
- Теперь Thread больше не проблема!
- Создание тысячи потоков стало дешёвым и быстрым:


try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
executor.submit(() -> System.out.println("Hello, Virtual Thread!"));
}


2️⃣ Pattern Matching для switch
- Больше не нужно кастовать вручную!

static void test(Object obj) {
switch (obj) {
case String s -> System.out.println("Это строка: " + s);
case Integer i when i > 0 -> System.out.println("Положительное число: " + i);
default -> System.out.println("Что-то другое");
}
}


3️⃣ Scoped Values (Альтернатива ThreadLocal)
- Теперь передача данных в потоки стала безопаснее!

static final ScopedValue<String> USER = ScopedValue.newInstance();
ScopedValue.runWhere(USER, "Admin", () -> System.out.println(USER.get()));


4️⃣ Record Patterns
- Улучшенный record, теперь можно удобно распаковывать данные:

record Point(int x, int y) {}
static void printPoint(Object obj) {
if (obj instanceof Point(int x, int y)) {
System.out.println("Координаты: " + x + ", " + y);
}
}


5️⃣ String Templates (в превью!)
- Упрощённое создание строк:

String name = "Alice";
String message = STR."Привет, \{name}!";


Java 21 делает язык ещё удобнее! Какая фича понравилась больше всего? 🤔

👉@BookJava

Читать полностью…

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

1️⃣ Чем record лучше class в Java?

В Java 14 появился record – новый тип классов, предназначенный для удобного хранения данных. Чем он лучше обычного class? Давайте разберёмся!

🔹 Запись против класса
Обычный класс:


class Person {
private final String name;
private final int age;

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

public String getName() { return name; }
public int getAge() { return age; }

@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + "}";
}
}

Много бойлерплейта…

Теперь то же самое с record:

record Person(String name, int age) {}

✅ Меньше кода
✅ Автоматически генерируются toString(), equals(), hashCode()
✅ Иммутабельность по умолчанию

⚠️ Когда НЕ стоит использовать record?
- Если нужен изменяемый объект
- Если требуется сложная бизнес-логика внутри класса

Вы уже используете record в своих проектах? Делитесь опытом! 🚀

👉@BookJava

Читать полностью…

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

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

Optional<T> в Java — это мощный инструмент для работы с возможными null значениями, но часто его используют неправильно. Давайте разберём основные ошибки и лучшие практики.

Плохие примеры:

1️⃣ Использование Optional как поля в классе


class User {
Optional<String> name; // ❌ Плохая практика
}

Лучше просто использовать String, а если нужно, то оборачивать значение в Optional при возврате.

2️⃣ Использование isPresent() вместо ifPresent()

if (optionalValue.isPresent()) {
process(optionalValue.get()); // ❌ Неоптимально
}

Лучше так:

optionalValue.ifPresent(this::process); // ✅ Правильный подход


📌 Хороший пример использования:

public Optional<User> findUserById(int id) {
return Optional.ofNullable(userRepository.get(id));
}


💡 Правильное использование Optional помогает избежать NullPointerException и делает код чище.

🔥 А как вы используете Optional? Пишите в комментариях! 🚀

👉@BookJava

Читать полностью…

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

Подборка Telegram каналов для программистов

Системное администрирование 📌
/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 разработчика

🦾👩‍💻🦾 Вы уже опытный Java-разработчик, но хотите освоить глубины JVM и оптимизацию приложений в облаке?

Курс «Java Developer. Advanced» — ваш билет к продвинутым технологиям, которые востребованы в крупных проектах.

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

Представьте, как ваши навыки открывают двери в серьёзные проекты с высокими требованиями. Наши преподаватели-практикующие эксперты поделятся опытом, а диплом OTUS станет отличным усилением к вашему резюме.

➡️ Это последний шанс попасть в группу! Регистрируйтесь сейчас и получите скидку: https://vk.cc/cI1cuV

🎫 ПРОМОКОД: Java_adv
Начните обучение со скидкой, подробности у менеджеров.

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru

Читать полностью…

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

👩‍💻 Пройди тест по Java и проверь свои знания, готов ли ты к обучению на курсе.

Ответишь — пройдешь на продвинутый курс "Java Developer. Professional" от OTUS по специальной цене + получишь доступ к записям открытых уроков курса курса

За 6 месяцев обучения вы научитесь создавать современные Java-приложения, освоите Spring WebFlux и Kafka, а также разберётесь в работе JVM изнутри.

Вас ждёт практическая работа с кодом, детальные разборы, ревью от экспертов и подходы, позволяющие писать эффективный и чистый код.

Начните свой путь к уровню Middle+!

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

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru

Читать полностью…

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

🖥️ Java: передача по значению или по ссылке? 🤔

В Java передача данных происходит ТОЛЬКО по значению (pass-by-value). Однако работа с объектами может ввести в заблуждение и создать впечатление, что передача идет по ссылке.

🔹 Как работает передача в Java?
Примитивные типы (`int`, `double`, `char`): передается копия значения. Изменения внутри метода не влияют на оригинальную переменную.

Объекты (экземпляры классов): передается копия ссылки на объект, а не сам объект. Внутри метода можно изменить состояние объекта, но нельзя изменить саму ссылку на него.

📌 Примеры
🔹 Передача примитивов (значение не изменяется)


public class Test {
public static void modifyPrimitive(int num) {
num = 10; // Это изменение локальное
}

public static void main(String[] args) {
int x = 5;
modifyPrimitive(x);
System.out.println(x); // Выведет: 5 (не изменилось)
}
}


🔹 Передача объекта (изменение состояния объекта сохраняется)

class Person {
String name;
}

public class Test {
public static void modifyObject(Person p) {
p.name = "Alice"; // Изменяет состояние объекта
}

public static void main(String[] args) {
Person person = new Person();
person.name = "Bob";
modifyObject(person);
System.out.println(person.name); // Выведет: Alice
}
}


🔹 Переназначение ссылки (не изменяет оригинальный объект)

class Person {
String name;
}

public class Test {
public static void reassignReference(Person p) {
p = new Person(); // Переназначение ссылки (локально)
p.name = "Charlie";
}

public static void main(String[] args) {
Person person = new Person();
person.name = "Bob";
reassignReference(person);
System.out.println(person.name); // Выведет: Bob (не изменилось)
}
}


🔥 Итог
🔹 Java всегда передает данные по значению!
🔹 Примитивы передаются как копии значений.
🔹 Объекты передаются как копии ссылок, но изменения внутри объекта сохраняются.
🔹 Если внутри метода изменить саму ссылку, это не повлияет на оригинальный объект.

👉@BookJava

Читать полностью…

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

Работа с временными метками в 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

Читать полностью…

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

Что спрашивают на собеседовании у Middle Java-разработчика?

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

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

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

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

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

Реклама. ООО "ШОРТКАТ", ИНН: 9731139396, erid: 2Vtzqw2cVob

Читать полностью…

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

🚀 5 полезных библиотек для Java-разработчика

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

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

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

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

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

👉@BookJava

Читать полностью…

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

📌 Паттерн "Одиночка" (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

Читать полностью…

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

Блокировки в 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

Читать полностью…

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

📌 Java Record: Почему Это Круто?

Сегодня расскажу вам о record в Java – мощном инструменте, который упростит вашу жизнь при работе с неизменяемыми объектами.

🔹 Что такое record?
Введённый в Java 14, record – это специальный тип класса, предназначенный для хранения данных. Он автоматически генерирует:
✅ Конструктор
✅ Геттеры (но без get в названии)
equals(), hashCode(), toString()

🔹 Пример использования


public record User(String name, int age) {}

Этот код эквивалентен написанию полноценного класса с полями, конструктором, геттерами и методами equals/hashCode/toString, но занимает всего одну строку!

🔹 Преимущества record
🚀 Меньше кода – никаких бойлерплейтов
🚀 Иммутабельность – данные не изменяются после создания
🚀 Читаемость – сразу видно, что это объект только для хранения данных

🔹 Ограничения:
❗ Поля record всегда final
❗ Наследование от record запрещено

👉@BookJava

Читать полностью…

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

🔹 Разбираем Lombok: как избавиться от шаблонного кода

Ты всё ещё пишешь getters и setters вручную? Используй Lombok!

💡 Как подключить?
Добавь в pom.xml:

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.26</version>
<scope>provided</scope>
</dependency>


💡 Как использовать?

import lombok.Data;

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


Теперь getName(), setName() и toString() сгенерируются автоматически!

👉 Lombok. Полное руководство

https://auth0.com/blog/a-complete-guide-to-lombok/

Кто уже использует Lombok в своих проектах?

👉@BookJava

Читать полностью…

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

🔥 5 паттернов проектирования, которые должен знать каждый Java-разработчик

В мире Java есть сотни паттернов проектирования, но эти 5 используются чаще всего. Если вы их освоите, ваш код станет чище, гибче и легче в поддержке.


1️⃣ Singleton
Ограничивает создание объекта одним экземпляром. Полезен для логирования, работы с базами данных, кэшей.

🔹 Пример кода (Lazy Initialization, thread-safe):


public class Singleton {
private static volatile Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}

Используется в Spring Bean, Hibernate SessionFactory.



2️⃣ Factory Method
Позволяет создавать объекты без привязки к конкретному классу. Отлично подходит, если у вас много типов объектов с общей логикой.

🔹 Пример:

interface Product {
void create();
}

class ConcreteProductA implements Product {
public void create() { System.out.println("Создан продукт A"); }
}

class ProductFactory {
public static Product createProduct(String type) {
if ("A".equals(type)) return new ConcreteProductA();
throw new IllegalArgumentException("Неизвестный тип продукта");
}
}

Используется в JDBC (DriverManager.getConnection).



3️⃣ Builder
Позволяет создавать сложные объекты пошагово. Альтернатива длинным конструкторам с кучей параметров.

🔹 Пример (Lombok @Builder делает его проще!):

@Builder
public class Car {
private String model;
private int year;
private String engine;
}

Car car = Car.builder().model("Tesla").year(2024).engine("Electric").build();

Используется в StringBuilder, HttpRequest в Java 11+.



4️⃣ Observer
Позволяет подписаться на события и реагировать на них. Часто используется в GUI, event-driven системах.

🔹 Пример (наблюдатель за событиями):

interface Observer {
void update(String message);
}

class User implements Observer {
private String name;
public User(String name) { this.name = name; }
public void update(String message) {
System.out.println(name + " получил уведомление: " + message);
}
}

class Channel {
private List<Observer> observers = new ArrayList<>();
public void subscribe(Observer o) { observers.add(o); }
public void notifyAll(String message) {
for (Observer o : observers) { o.update(message); }
}
}

Используется в Spring Events, RxJava.



5️⃣ Decorator
Добавляет функциональность объекту без изменения его структуры. Часто применяется в логгировании, кешировании, потоках IO.

🔹 Пример (логирование обертки над OutputStream):

class LoggingOutputStream extends OutputStream {
private OutputStream wrapped;
public LoggingOutputStream(OutputStream wrapped) { this.wrapped = wrapped; }
@Override
public void write(int b) throws IOException {
System.out.println("Записываем байт: " + b);
wrapped.write(b);
}
}

Используется в BufferedReader, Logger, Spring Security Filters.



💬 Ну и в заключение
Если вы хотите писать гибкий и масштабируемый код, обязательно используйте паттерны проектирования. А какие из них вы используете в своих проектах чаще всего? Делитесь в комментариях! 🚀

👉@BookJava

Читать полностью…

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

👩‍💻Ваши приложения готовы к перегрузкам? А если вдруг лавина запросов?

На открытом вебинаре «Resilience4j. Bulkhead» вы узнаете, как защитить свои сервисы от сбоев. Разберём ключевые возможности Bulkhead и покажем, как ограничение ресурсов может спасти приложение.

Хотите углубить навыки бэкенд-разработки, повысить устойчивость своих микросервисов и освоить Resilience4j?

🗓 Всё это уже 12 февраля в 20:00 мск!

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

➡️ Регистрируйтесь на открытый урок прямо сейчас! Участники получат скидку на большое обучение на курс «Java Developer. Professional»: https://vk.cc/cIfjod

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576

Читать полностью…

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

🔥 Разбираем CompletableFuture: Асинхронность в Java без боли

Привет, коллеги! Сегодня поговорим о CompletableFuture, который помогает писать асинхронный код в Java без коллбэков и потерь в читабельности.

📌 1. Почему CompletableFuture?
В Java давно есть Future, но он неудобен:
❌ Нельзя комбинировать несколько задач.
❌ Блокирует поток при вызове .get().
❌ Нет удобных методов для обработки результатов.

👉 CompletableFuture решает все эти проблемы, позволяя комбинировать задачи, обрабатывать ошибки и не блокировать потоки.



📌 2. Базовый пример использования


import java.util.concurrent.CompletableFuture;

public class AsyncExample {
public static void main(String[] args) {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
sleep(2000);
return "Привет, мир!";
});

future.thenAccept(result -> System.out.println("Результат: " + result));

System.out.println("Этот текст выведется раньше результата!");
sleep(3000); // Чтобы программа не завершилась раньше времени
}

private static void sleep(int ms) {
try { Thread.sleep(ms); } catch (InterruptedException ignored) {}
}
}

🔹 Здесь supplyAsync() выполняет задачу в другом потоке, а thenAccept() позволяет асинхронно обработать результат.



📌 3. Комбинирование нескольких задач

CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Hello");
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "World");

CompletableFuture<String> result = future1.thenCombine(future2, (s1, s2) -> s1 + " " + s2);

System.out.println(result.join()); // Hello World

thenCombine() объединяет результаты двух асинхронных задач.



📌 4. Обработка ошибок (exceptionally)

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
if (Math.random() > 0.5) {
throw new RuntimeException("Что-то пошло не так!");
}
return "Все хорошо!";
}).exceptionally(ex -> "Ошибка: " + ex.getMessage());

System.out.println(future.join());

✅ Если в supplyAsync() произошла ошибка, она обработается в exceptionally(), и программа не упадёт.



📌 5. Запуск нескольких задач параллельно

CompletableFuture<Void> allTasks = CompletableFuture.allOf(
CompletableFuture.runAsync(() -> sleepAndPrint("Задача 1", 1000)),
CompletableFuture.runAsync(() -> sleepAndPrint("Задача 2", 2000)),
CompletableFuture.runAsync(() -> sleepAndPrint("Задача 3", 1500))
);

allTasks.join(); // Дождёмся завершения всех задач

private static void sleepAndPrint(String msg, int ms) {
try { Thread.sleep(ms); } catch (InterruptedException ignored) {}
System.out.println(msg);
}

allOf() позволяет запустить несколько задач параллельно и дождаться их завершения.



📌 Итог
🔹 CompletableFuture – это мощный инструмент для работы с асинхронностью в Java.
🔹 Позволяет избежать блокировок, обрабатывать ошибки, комбинировать задачи.
🔹 Улучшает читаемость кода по сравнению с Future и ExecutorService.

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

👉@BookJava

Читать полностью…

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

🚀Разбираем принцип работы ConcurrentHashMap

Сегодня разберёмся, почему ConcurrentHashMap лучше подходит для многопоточной работы, чем HashMap, и как он работает внутри.

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

📌 Основные особенности:
- Делит данные на сегменты (до JDK 8 или использует synchronized и CAS операции (начиная с JDK 8).
- Чтение (get()) не требует блокировки.
- Запись (put()) использует минимально возможные блокировки.
- Нет null ключей и значений (в отличие от HashMap).

Пример использования:


import java.util.concurrent.ConcurrentHashMap;

public class Main {
public static void main(String[] args) {
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();

map.put("Java", 1);
map.put("Python", 2);
map.put("C++", 3);

System.out.println(map.get("Java")); // 1
}
}


А вы часто используете ConcurrentHashMap? Поделитесь в комментариях! 👇

👉@BookJava

Читать полностью…

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

В чем разница между Checked и Unchecked исключениями во время выполнения?

Да, в Java есть существенные различия между checked (проверяемыми) и unchecked (непроверяемыми) исключениями во время выполнения.

1. Проверка на этапе компиляции
- Checked исключения: Проверяются на этапе компиляции. Компилятор требует, чтобы вы либо обработали исключение (с помощью try-catch), либо объявили его в сигнатуре метода (с помощью throws). Если этого не сделать, код не скомпилируется.
- Unchecked исключения: Не проверяются на этапе компиляции. Компилятор не требует их обработки или объявления. Обычно они возникают из-за логических ошибок в коде (например, NullPointerException, ArrayIndexOutOfBoundsException).

2. Поведение во время выполнения
- Checked исключения: Эти исключения обычно связаны с внешними факторами (например, проблемы с файловым вводом-выводом, сетевыми соединениями) и могут возникать в ходе нормального выполнения программы. Если такое исключение выбрасывается и не обрабатывается, оно будет передаваться вверх по стеку вызовов, пока не будет перехвачено или программа не завершится.
- Unchecked исключения: Эти исключения часто вызваны ошибками в коде (например, деление на ноль, обращение к null). Если такое исключение выбрасывается и не перехватывается, оно также будет передаваться вверх по стеку вызовов, но, поскольку их не требуется объявлять или обрабатывать, это может привести к неожиданному завершению программы.

3. Наследование
- Checked исключения: Все исключения, которые наследуют Exception (но не RuntimeException), являются проверяемыми.
- Unchecked исключения: Все исключения, которые наследуют RuntimeException или Error, являются непроверяемыми.

4. Примеры
- Checked исключения: IOException, SQLException, ClassNotFoundException.
- Unchecked исключения: NullPointerException, ArrayIndexOutOfBoundsException, ArithmeticException.

5. Обработка во время выполнения
- Checked исключения: Поскольку они проверяются на этапе компиляции, вы обязаны явно их обрабатывать. Это делает код более устойчивым, но может увеличить его объем.
- Unchecked исключения: Поскольку они не проверяются на этапе компиляции, их сложнее отлаживать и обрабатывать, так как они могут быть неочевидными в коде.

6. Производительность
- Нет значительной разницы в производительности между checked и unchecked исключениями во время выполнения. Стоимость выбрасывания и перехвата исключений одинакова для обоих типов.

Итог
- Checked исключения: Контролируются компилятором, должны быть обработаны или объявлены, обычно используются для recoverable (восстанавливаемых) ситуаций.
- Unchecked исключения: Не контролируются компилятором, часто возникают из-за ошибок в коде и могут привести к аварийному завершению программы, если не обработаны.

Оба типа исключений ведут себя схожим образом во время выполнения, но ключевое различие заключается в том, как они контролируются и обрабатываются на этапе разработки.

👉@BookJava

Читать полностью…

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

🚀 Совет по Java API 🚀

При использовании Integer.valueOf(int) помните, что значения в диапазоне от -128 до 127 кэшируются для повышения производительности. За пределами этого диапазона создаются новые объекты.

Размер кэша можно контролировать с помощью опции -XX:AutoBoxCacheMax=<размер>. 🔥

👉@BookJava

Читать полностью…

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

Совет по Java 💡☕️

Чтобы получить все дни месяца, вы можете начать с объекта YearMonth, получить его первый день, а затем использовать функцию datesUntil(), которая возвращает Stream всех дней до указанной даты.

👉@BookJava

Читать полностью…

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

⚡️ Хотите управлять приложениями на Java и Kotlin, как дирижер оркестром?

Spring Framework — ключевой инструмент для создания мощных Java-приложений. Вы научитесь проектировать микросервисы, внедрять Spring Boot, разрабатывать безопасные системы с Spring Security и решать задачи уровня Middle+.

🦾 На курсе вас ждут живые лекции, реальные задачи и экспертное ревью кода. Ваш диплом от OTUS – билет в крупные компании!

Присоединяйтесь к курсу и прокачайте Java-навыки на Spring до профессионального уровня.

📌 Регистрация открыта — успейте записаться: https://vk.cc/cHWc3z

🎫 ПРОМОКОД: Spring_01
Начни обучение со скидкой, подробности у менеджеров.

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru

Читать полностью…
Subscribe to a channel