Библиотека 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
Сегодня покажу вам 🧠 один тонкий момент в работе с Optional, который часто ловит даже опытных.

Многие пишут так:


Optional<String> optional = getValue();
if (optional.isPresent()) {
doSomething(optional.get());
}


⚠️ Это антипаттерн! Вы теряете суть Optional и рискуете ошибками в многопоточке.

📌 Правильный способ — использовать функциональный стиль:


getValue().ifPresent(this::doSomething);


Или ещё элегантнее:


getValue()
.map(this::transform)
.filter(this::isValid)
.ifPresent(this::doSomething);


💡 Подходы:
- map для преобразования значения
- filter для отсеивания ненужных
- orElse, orElseGet, orElseThrow для обработки отсутствия
- ifPresentOrElse в Java 9+ для двух вариантов действий

📈 Выгоды:
- Код становится компактнее
- Безопаснее при рефакторинге
- Лучше для чтения в потоковых операциях (Stream API)

🛠 Если нужно вынуть значение — используйте orElseThrow() вместо .get():


String value = getValue().orElseThrow(() -> new IllegalStateException("Value not found"));


👉 Отказывайтесь от .isPresent() и .get() связки — используйте силу функционального подхода! 🚀

👉@BookJava
👍7👎5
🚀 Подборка Telegram каналов для программистов

Системное администрирование, DevOps 📌

https://t.me/bash_srv Bash Советы
https://t.me/win_sysadmin Системный Администратор Windows
https://t.me/sysadmin_girl Девочка Сисадмин
https://t.me/srv_admin_linux Админские угодья
https://t.me/linux_srv Типичный Сисадмин
https://t.me/devopslib Библиотека девопса | DevOps, SRE, Sysadmin
https://t.me/linux_odmin Linux: Системный администратор
https://t.me/devops_star DevOps Star (Звезда Девопса)
https://t.me/i_linux Системный администратор
https://t.me/linuxchmod Linux
https://t.me/sys_adminos Системный Администратор
https://t.me/tipsysdmin Типичный Сисадмин (фото железа, было/стало)
https://t.me/sysadminof Книги для админов, полезные материалы
https://t.me/i_odmin Все для системного администратора
https://t.me/i_odmin_book Библиотека Системного Администратора
https://t.me/i_odmin_chat Чат системных администраторов
https://t.me/i_DevOps DevOps: Пишем о Docker, Kubernetes и др.
https://t.me/sysadminoff Новости Линукс Linux

1C разработка 📌
https://t.me/odin1C_rus Cтатьи, курсы, советы, шаблоны кода 1С
https://t.me/DevLab1C 1С:Предприятие 8
https://t.me/razrab_1C 1C Разработчик
https://t.me/buh1C_prog 1C Программист | Бухгалтерия и Учёт
https://t.me/rabota1C_rus Вакансии для программистов 1С

Программирование C++📌
https://t.me/cpp_lib Библиотека C/C++ разработчика
https://t.me/cpp_knigi Книги для программистов C/C++
https://t.me/cpp_geek Учим C/C++ на примерах

Программирование Python 📌
https://t.me/pythonofff Python академия.
https://t.me/BookPython Библиотека Python разработчика
https://t.me/python_real Python подборки на русском и английском
https://t.me/python_360 Книги по Python

Java разработка 📌
https://t.me/BookJava Библиотека Java разработчика
https://t.me/java_360 Книги по Java Rus
https://t.me/java_geek Учим Java на примерах

GitHub Сообщество 📌
https://t.me/Githublib Интересное из GitHub

Базы данных (Data Base) 📌
https://t.me/database_info Все про базы данных

Мобильная разработка: iOS, Android 📌
https://t.me/developer_mobila Мобильная разработка
https://t.me/kotlin_lib Подборки полезного материала по Kotlin

Фронтенд разработка 📌
https://t.me/frontend_1 Подборки для frontend разработчиков
https://t.me/frontend_sovet Frontend советы, примеры и практика!
https://t.me/React_lib Подборки по React js и все что с ним связано

Разработка игр 📌
https://t.me/game_devv Все о разработке игр

Библиотеки 📌
https://t.me/book_for_dev Книги для программистов Rus
https://t.me/programmist_of Книги по программированию
https://t.me/proglb Библиотека программиста
https://t.me/bfbook Книги для программистов

БигДата, машинное обучение 📌
https://t.me/bigdata_1 Big Data, Machine Learning

Программирование 📌
https://t.me/bookflow Лекции, видеоуроки, доклады с IT конференций
https://t.me/rust_lib Полезный контент по программированию на Rust
https://t.me/golang_lib Библиотека Go (Golang) разработчика
https://t.me/itmozg Программисты, дизайнеры, новости из мира IT
https://t.me/php_lib Библиотека PHP программиста 👨🏼‍💻👩‍💻
https://t.me/nodejs_lib Подборки по Node js и все что с ним связано
https://t.me/ruby_lib Библиотека Ruby программиста
https://t.me/lifeproger Жизнь программиста. Авторский канал.

QA, тестирование 📌
https://t.me/testlab_qa Библиотека тестировщика

Шутки программистов 📌
https://t.me/itumor Шутки программистов

Защита, взлом, безопасность 📌
https://t.me/thehaking Канал о кибербезопасности
https://t.me/xakep_2 Хакер Free

Книги, статьи для дизайнеров 📌
https://t.me/ux_web Статьи, книги для дизайнеров

Математика 📌
https://t.me/Pomatematike Канал по математике
https://t.me/phis_mat Обучающие видео, книги по Физике и Математике
https://t.me/matgeoru Математика | Геометрия | Логика

Excel лайфхак📌
https://t.me/Excel_lifehack

https://t.me/mir_teh Мир технологий (Technology World)

Вакансии 📌
https://t.me/sysadmin_rabota Системный Администратор
https://t.me/progjob Вакансии в IT
🔥1
📌 Ошибка: Вызов метода с @Transactional внутри того же класса не запускает новую транзакцию.

Почему? Spring оборачивает бин в прокси, а внутренние вызовы проходят мимо прокси, значит, аннотация игнорируется.

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

@Service
public class OrderService {

@Transactional
public void createOrder() {
saveOrder();
}

@Transactional
public void saveOrder() {
// Новый транзакционный контекст не создастся!
}
}


💡 Как правильно:
1. Вынести saveOrder() в отдельный бин.
2. Или получить прокси текущего бина через AopContext:


@Service
@EnableAspectJAutoProxy(exposeProxy = true) // важно!
public class OrderService {

@Transactional
public void createOrder() {
((OrderService) AopContext.currentProxy()).saveOrder();
}

@Transactional
public void saveOrder() {
// Теперь всё ок
}
}


⚠️ Важный момент: exposeProxy = true нужен на уровне конфигурации, иначе AopContext не заработает.


Понимание этой тонкости критично для корректного управления транзакциями в Spring! 🚀

👉@BookJava
👍5👎3
🧠 Сегодня покажу вам полезный трюк для Spring Boot: как элегантно валидировать параметры контроллера без лишнего кода.

Часто вижу, как в контроллерах вручную проверяют @RequestParam на пустоту или формат. Это шумит код и приводит к ошибкам.

Вместо этого используйте аннотации валидации прямо на параметрах:


@RestController
@RequestMapping("/api")
@Validated // Обязательно!
public class UserController {

@GetMapping("/users")
public List<User> getUsers(
@RequestParam @NotBlank String name,
@RequestParam @Min(18) int age
) {
// Если валидация не пройдена — автоматически вернётся 400 Bad Request
return userService.findUsers(name, age);
}
}


📌 Ключевые моменты:
- Обязательно ставим @Validated над классом контроллера.
- На параметры добавляем любые стандартные аннотации из jakarta.validation.constraints.
- Ошибки валидации Spring обработает автоматически через MethodArgumentNotValidException.

💡 Можно кастомизировать ответ на ошибку, добавив глобальный @ExceptionHandler.

⚠️ Без @Validated аннотации на контроллере валидация параметров работать не будет!

👉@BookJava
👍10
Есть фича. Есть дедлайн. Есть понимание, что тесты надо писать… но они отъедают время, которого итак впритык.

Один наш знакомый девелопер сказал: «С тех пор как поставил Explyt Test — начал писать меньше тестов… но покрытие стало лучше. Как это вообще возможно?!»

Попробуйте сами. Плагин сам предлагает тесты для вашего кода — прямо в IDE.
👉 explyt.ai — сэкономь себе пару часов уже сегодня.
👍4🔥1
В Java instance initializer blocks (блоки инициализации экземпляра) выполняются в следующем порядке:

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

Порядок инициализации:

1. Сначала инициализируются поля в порядке их объявления.
2. Затем выполняются instance initializer blocks, в том порядке, в котором они написаны в коде.
3. После этого выполняется тело конструктора.

Пример:


class Example {
int x = 10;

{
System.out.println("Instance initializer block");
x = 20;
}

Example() {
System.out.println("Constructor");
System.out.println("x = " + x);
}

public static void main(String[] args) {
Example ex = new Example();
}
}


Вывод:

Instance initializer block
Constructor
x = 20


Ключевые моменты:
- Статические блоки (static {}) — другое дело: они выполняются один раз при загрузке класса.
- Instance initializer blocks полезны для общей инициализации, которую нужно выполнять вне зависимости от того, какой конструктор вызывается.

👉@BookJava
👍7🔥3
Как работают instance initializer blocks.


Пример с родительским и дочерним классами:


class Parent {
int a = 5;

{
System.out.println("Parent instance initializer");
a = 10;
}

Parent() {
System.out.println("Parent constructor, a = " + a);
}
}

class Child extends Parent {
int b = 15;

{
System.out.println("Child instance initializer");
b = 25;
}

Child() {
System.out.println("Child constructor, b = " + b);
}
}

public class Test {
public static void main(String[] args) {
Child child = new Child();
}
}



Вывод программы:


Parent instance initializer
Parent constructor, a = 10
Child instance initializer
Child constructor, b = 25


Пошаговое выполнение:

1. Сначала загружается родительский класс Parent.
2. Выполняется:
- Инициализация полей родителя (a = 5),
- Потом instance initializer блока родителя (a = 10),
- Потом конструктор родителя (Parent()).
3. Далее переходим к дочернему классу Child:
- Инициализация полей дочернего класса (b = 15),
- Потом instance initializer блока дочернего класса (b = 25),
- Потом конструктор дочернего класса (Child()).


Важный порядок действий:

1. Инициализация родителя → 2. Конструктор родителя → 3. Инициализация потомка → 4. Конструктор потомка.

Блоки инициализации всегда выполняются до тела конструктора, но после вызова super().

👉@BookJava
👍6
💡Сегодня покажу крутую фишку для оптимизации чтения больших коллекций из базы через JPA.


📌 Проблема:
Когда загружаем большую коллекцию через @OneToMany, Hibernate часто делает это лениво (LAZY), но при первом доступе — забирает всю коллекцию целиком.
Это может привести к OutOfMemoryError или резкому проседанию производительности.


📌 Решение: использовать пагинацию (batch-size) или запрос коллекции порциями.

Как настроить batch-size на уровне сущности:


@Entity
public class User {

@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
@BatchSize(size = 50)
private List<Order> orders;
}


🧠 Теперь Hibernate будет загружать за раз по 50 элементов, а не всю коллекцию сразу!


📌 Или можно настроить глобально через application.properties:


spring.jpa.properties.hibernate.default_batch_fetch_size=50



⚠️ Важно:

- @BatchSize работает только для LAZY-связей.
- Это не пагинация в SQL, а оптимизация внутренних запросов Hibernate.
- Если коллекция огромная (100k+ записей) — лучше делать явные paged запросы в репозитории.

💡Помните: без настройки batch-size Hibernate может сломать приложение под нагрузкой. Оптимизируйте загрузку коллекций заранее!

👉@BookJava
🔥6👍31
🤖 А ты справишься с тестом по Kotlin?

🏆 Пройди тест из 10 вопросов, проверь свой уровень знаний и получи скидку на онлайн-курс «Kotlin Backend Developer. Professional» от OTUS!

Если успешно пройдешь тест, сможешь забронировать место в группе по выгодной цене! И еще дарим промокод Kotlin5

🎫
Курс можно приобрести в рассрочку

➡️ Пройти тест и забрать скидку: https://vk.cc/cLkRLn

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM
🧠 Как в Java сломать equals() и потерять данные в HashMap

Сегодня покажу, как неочевидный баг в equals()/hashCode() может привести к потере данных при работе с HashMap.

Допустим, у вас есть Entity:


public class User {
private String id;
private String name;

// equals/hashCode только по id
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof User)) return false;
User user = (User) o;
return Objects.equals(id, user.id);
}

@Override
public int hashCode() {
return Objects.hash(id);
}
}


Вроде норм. Но теперь добавим такого юзера в HashMap, а потом... изменим его id:


User user = new User();
user.setId("1");
user.setName("Alice");

Map<User, String> map = new HashMap<>();
map.put(user, "value");

user.setId("2"); // ⚠️ ключ стал "невидимым"

System.out.println(map.get(user)); // null 😱


📌 Почему так происходит?

HashMap ищет ключ по hashCode() → ищет бакет → сравнивает через equals(). А hashCode() уже другой, и объект "теряется".

💡 Совет: если вы используете объект как ключ в мапе или добавляете его в Set, не изменяйте его поля, участвующие в equals()/hashCode()!

📌 А как правильно?

- Делайте такие поля final;
- Или используйте неизменяемые типы (record);
- Или не используйте такие объекты как ключи вовсе.

Вот безопасный вариант с record:


public record User(String id, String name) {}


👉@BookJava
👍5
Java. Сортировки

Java. Сортировка пузырьком.
Java. О сортировке выбором.
Java. Быстрая сортировка. Объяснение на пальцах)
Java. Оценка сложности алгоритмов сортировки.
Java. Сортировка слиянием.
Java. Сортировка подсчетом.
Java. Сортировка вставками.
Java. Сортировка расческой. От пузырька до расчески.

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

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

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

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

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

Если успешно пройдешь тест, сможешь забронировать место в группе по выгодной цене! И еще дарим промокод SPRING5

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
👍1👎1
🧠 Знаешь ли ты, что @Transactional на private - методах не работает?

Да, Spring просто не применяет прокси к private-методам. Это частый баг, который трудно отловить: ты вызываешь приватный метод внутри бина, а транзакция… не начинается 🤷‍♂️

📌 Почему так происходит?
Spring AOP по умолчанию использует динамические прокси (JDK или CGLIB), которые перехватывают внешние вызовы. А вызов private - метода из того же класса — это внутренний вызов, который обходит прокси.

Пример, который НЕ работает:


@Service
public class UserService {

public void createUser() {
saveUser(); // Вызов мимо прокси 😞
}

@Transactional
private void saveUser() {
// Транзакция НЕ начнется!
}
}


💡 Как правильно:
1. Сделай метод public или хотя бы protected,
2. Или выноси в отдельный бин:


@Service
public class UserService {

private final TxUserSaver txUserSaver;

public UserService(TxUserSaver txUserSaver) {
this.txUserSaver = txUserSaver;
}

public void createUser() {
txUserSaver.saveUser(); // Теперь через прокси
}
}

@Service
public class TxUserSaver {

@Transactional
public void saveUser() {
// Всё сработает как надо
}
}


⚠️ Проверь свои сервисы — ты можешь удивиться, сколько транзакций у тебя не работают. Особенно в проектах, где @Transactional ставят "на всякий случай".

👉@BookJava
👍4