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


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

РКН clck.ru/3KoGeP
Download Telegram
Многопоточность

Как можно создать потоки в Java?
Как устроить Deadlock, а затем уйти от взаимной блокировки навсегда
Два самых полезных слова в многопоточности join() и Future

источник

📲 Мы в MAX

👉@BookJava
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
👩‍💻 Ваши Java-приложения под нагрузкой едва дышат? Профилирование и оптимизация кода остаются за скобками?

🎯 Курс «Java Developer. Advanced» от OTUS — это глубокое погружение в устройство JVM, байткод, сборщики мусора, профилирование и оптимизацию в облаке.
Наши эксперты-практики покажут, как выбрать GC, снять дамп памяти и обнаружить утечки, как профилировать “горячие” места, настраивать интеграцию с Prometheus & Grafana и деплоить сервисы в Kubernetes.

✔️ Вы научитесь обосновывать выбор JVM-имплементации, анализировать heap-дампы, синхронизировать потоки, использовать Reactor и неблокирующие I/O, проектировать метрики и трассировку.

➡️ Пройдите короткий тест и присоединяйтесь к группе: https://vk.cc/cRBJWK

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

Использование try-with-resources для автоматического управления ресурсами
Оператор try-with-resources гарантирует, что каждый ресурс будет закрыт в конце оператора.


try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}


📲 Мы в MAX

👉@BookJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Что такое «ссылка на метод»?

Если существующий в классе метод уже делает все, что необходимо, то можно воспользоваться механизмом method reference (ссылка на метод) для непосредственной передачи этого метода. Такая ссылка передается в виде:

⚫️имя_класса::имя_статического_метода для статического метода;
⚫️объект_класса::имя_метода для метода экземпляра;
⚫️название_класса::new для конструктора.
Результат будет в точности таким же, как в случае определения лямбда-выражения, которое вызывает этот метод.


private interface Measurable {
public int length(String string);
}

public static void main(String[] args) {
Measurable a = String::length;
System.out.println(a.length("abc"));
}


Ссылки на методы потенциально более эффективны, чем использование лямбда-выражений. Кроме того, они предоставляют компилятору более качественную информацию о типе и при возможности выбора между использованием ссылки на существующий метод и использованием лямбда-выражения, следует всегда предпочитать использование ссылки на метод.

📲 Мы в MAX

👉@BookJava
👍41
Использование Optional для избежания NullPointerException:
Optional — это контейнер, который может содержать или не содержать ненулевое значение.


Optional<String> optional = Optional.ofNullable(getValue());
optional.ifPresentOrElse(
value -> System.out.println("Value is present: " + value),
() -> System.out.println("Value is absent")
);


📲 Мы в MAX

👉@BookJava
👍6
⚡️ Микро-оптимизация: Прощай, AtomicInteger, привет, VarHandle!

👋 Сегодня поговорим о том, как можно немного ускорить ваш код, работающий с атомарными операциями, и сделать его более "современным" с помощью VarHandle, который появился в Java 9.

🧐 Проблема с AtomicInteger

AtomicInteger - это классический способ обеспечить атомарные операции (например, инкремент) над целым числом без блокировок, используя механизм Compare-And-Swap (CAS).

Однако, у него есть небольшой недостаток: он добавляет слой косвенности. Методы типа getAndIncrement() в AtomicInteger обычно вызывают внутренние статические методы из класса sun.misc.Unsafe (или его аналогов в более новых версиях), передавая в них ссылку на объект, смещение поля и новое значение.


// Примерно так это выглядит внутри AtomicInteger
// В реальном коде это, конечно, оптимизировано, но суть та же.
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
}


Встречайте VarHandle!

VarHandle - это новый, более гибкий и, что самое главное, более производительный низкоуровневый API для работы с полями переменных (как экземпляров, так и статических) с заданными барьерами памяти и атомарностью.

Главное преимущество? JIT-компилятор (C2) лучше оптимизирует доступ через VarHandle, чем через старые обертки типа AtomicInteger или прямые вызовы Unsafe.

🛠 Как использовать VarHandle вместо AtomicInteger

Вместо того, чтобы хранить значение в отдельном объекте AtomicInteger, мы просто объявляем поле volatile в нашем классе и получаем VarHandle для этого поля.

1. Объявляем поле:


public class Counter {
private volatile int count = 0; // Поле должно быть volatile
// ...
}


2. Создаем VarHandle:

VarHandle нужно инициализировать один раз (обычно в статическом блоке) для доступа к полю.


private static final VarHandle COUNT_HANDLE;

static {
try {
// Получаем VarHandle для поля 'count' класса 'Counter' с типом int
COUNT_HANDLE = MethodHandles.lookup().findVarHandle(
Counter.class,
"count",
int.class
);
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new Error(e);
}
}


3. Выполняем атомарную операцию:

Метод getAndAdd VarHandle работает точно так же, как getAndAdd в AtomicInteger.


public int increment() {
// В отличие от AtomicInteger, где первый аргумент неявен,
// VarHandle требует первым аргументом *объект*,
// к полю которого мы обращаемся.
return (int) COUNT_HANDLE.getAndAdd(this, 1);
}


🚀 Результат микро-оптимизации

В бенчмарках (например, с использованием JMH) можно увидеть, что операции getAndAdd() через VarHandle могут быть незначительно быстрее (зачастую на 5-10%), чем те же операции через AtomicInteger, особенно под высокой нагрузкой, благодаря более эффективной генерации кода JIT-компилятором.

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



VarHandle - это не только способ микро-оптимизации, но и стандартный, гибкий API для атомарного доступа, который заменил устаревший и менее безопасный Unsafe. Для нового кода, где требуется низкоуровневый атомарный доступ, стоит отдавать предпочтение именно ему.

📲 Мы в MAX

👉@BookJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5👎5🔥1
Совет

По умолчанию при обновлении сущности Hibernate обновляет все ее поля. Вы можете использовать аннотацию @DynamicUpdate на объекте
@Entity и Hibernate будет обновлять только те столбцы, которые изменились.



📲 Мы в MAX

👉@BookJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10
Совет SpringBoot

Вы можете запустить метод в Spring @Service сразу после запуска приложения, аннотируя его с помощью
@EventListener (ApplicationReadyEvent.class). Метод не может иметь параметров. Иногда я неправильно использую его, чтобы быстро протестировать определенный метод Spring Service.

📲 Мы в MAX

👉@BookJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🏆1
Использование лямбда-выражений и Streams:
Лямбда-выражения и streams делают код более лаконичным и читаемым.


List<String> names = Arrays.asList("John", "Jane", "Jack", "Doe");
names.stream()
.filter(name -> name.startsWith("J"))
.map(String::toUpperCase)
.forEach(System.out::println);


📲 Мы в MAX

👉@BookJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👎4👍3
☕️ Spring Core: Зачем нужна аннотация @Bean?

Если вы работаете со Spring, вы видите эту аннотацию постоянно. Но чем она отличается от простого навешивания @Component над классом? Давайте разберем.

💡 Что это такое?

Аннотация @Bean используется в методах конфигурационных классов (помеченных @Configuration). Она говорит Spring-контейнеру:

"Эй, Spring! Выполни этот метод, возьми то, что он вернет, и сохрани этот объект у себя в контексте (ApplicationContext). Управляй им как бином".


🛠 Как это выглядит?


@Configuration
public class AppConfig {

// Мы явно создаем объект и отдаем его Спрингу
@Bean
public ObjectMapper objectMapper() {
return new ObjectMapper(); // Например, библиотека Jackson
}
}




🔥 Когда использовать @Bean, а когда @Component?

Это самый частый вопрос на собеседованиях.

1. Используйте @Component@Service, @Repository), когда:

- Это ваш класс. Вы имеете доступ к исходному коду.
- Вам нужна магия автоматического сканирования (component scanning). Вы просто ставите аннотацию над классом, и Spring сам его находит.

2. Используйте @Bean, когда:

- Сторонние библиотеки. Вы не можете зайти в класс ObjectMapper (из Jackson) или AmazonS3Client и написать там @Component, потому что это чужой код (read-only). Чтобы добавить такой объект в контекст Spring, вы создаете для него метод с @Bean.
- Сложная логика создания. Если создание объекта требует условий (if/else) или сложной конфигурации, проще описать это в методе явно.

⚙️ Фишки @Bean

- Имена: По умолчанию имя бина совпадает с именем метода. Можно изменить: @Bean("myCoolBean").
- Init/Destroy: Можно указать методы, которые сработают при создании или удалении бина: @Bean(initMethod = "init", destroyMethod = "cleanup").
- Зависимости: Если методу с @Bean нужны аргументы, Spring автоматически найдет и подставит их из контекста.

Итог: @Component - для автоматизации своих классов, @Bean - для ручного контроля и чужих библиотек.


#Java #Spring #SpringBoot #Coding #Education

📲 Мы в MAX

👉@BookJava
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3👍1
🔍 Завтра тестовое собеседование с Java-разработчиком

17 декабря(уже завтра!) в 19:00 по мск приходи онлайн на открытое собеседование, чтобы посмотреть на настоящее интервью на Middle Java-разработчика.

Как это будет:
📂 Сергей Чамкин, старший разработчик из Uzum, ex-WildBerries, будет задавать реальные вопросы и задачи разработчику-добровольцу
📂 Cергей будет комментировать каждый ответ респондента, чтобы дать понять чего от вас ожидает собеседующий на интервью
📂 В конце можно будет задать любой вопрос Сергею

Это бесплатно. Эфир проходит в рамках менторской программы от ШОРТКАТ для Java-разработчиков, которые хотят повысить свой грейд, ЗП и прокачать скиллы.

Переходи в нашего бота, чтобы получить ссылку на эфир →
@shortcut_sh_bot

Реклама.
О рекламодателе.
Please open Telegram to view this post
VIEW IN TELEGRAM
Совет Spring Framework💡

Вы можете инжектировать (autowire) бины, которые могут отсутствовать, обернув их в java.util.Optional. Таким образом вы сообщаете, что этот бин является необязательным, избегаете исключения, если он не существует, и можете аккуратно обработать его отсутствие с помощью Optional API.

📲 Мы в MAX

👉@BookJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍41
⌨️ Открытый урок «Тестирование Spring приложений. Интеграционные тесты с контекстом. Тестирование слоя репозиториев и сервисов».

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

Интеграционные тесты в Spring: тестовый контекст, репозитории (JDBC/JPA), сервисы и транзакции.

На вебинаре:
✔️Особенности интеграционных тестов с поднятием контекста Spring.
✔️Тестирование слоя репозиториев: JDBC и JPA.
✔️Работа с транзакциями на сервисном слое и подходы к тестированию.

Кому будет полезно:
Backend-разработчикам на Java, начинающим осваивать тестирование Spring-приложений.

Что вы получите:
Разберётесь в базе интеграционного тестирования со Spring-контекстом и сможете написать простые тесты для репозиториев и сервисов.

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

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

Помните те времена, когда для объединения списка строк через запятую приходилось писать циклы, использовать StringBuilder, а потом еще и аккуратно удалять последний разделитель? 🤯

Начиная с Java 8, у нас есть элегантный статический метод String.join, который делает код чистым и читаемым.

🛠 Как это работает?

Метод принимает разделитель (delimiter) и элементы, которые нужно склеить. Элементами могут быть как просто перечисление строк (varargs), так и любая коллекция (Iterable).

1️⃣ Пример с перечислением строк:


String result = String.join(" -> ", "Wake up", "Code", "Sleep");

System.out.println(result);
// Вывод: Wake up -> Code -> Sleep


2️⃣ Пример с коллекцией (List, Set):


List<String> langs = Arrays.asList("Java", "Kotlin", "Groovy");

// Больше никаких циклов!
String output = String.join(" | ", langs);

System.out.println(output);
// Вывод: Java | Kotlin | Groovy


🧐 Важные нюансы:

- Null-safe (частично): Если сам список или массив равен null, вы получите NullPointerException. Но если null является одним из элементов списка, метод просто преобразует его в строку "null".
- Под капотом: Метод использует StringJoiner (еще один класс из Java 8), что обеспечивает неплохую производительность по сравнению с обычной конкатенацией через +.

🚀 Когда использовать?

Используйте String.join, когда у вас уже есть коллекция или массив строк, и вам нужно быстро собрать их в одну строку.

Если же вы работаете со Stream API, то лучше подойдет коллектор:
.collect(Collectors.joining(", "))


#Java #Core #Tips #CleanCode

📲 Мы в MAX

👉@BookJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2