Java Geek
2.49K subscribers
256 photos
1 file
16 links
Практичные советы, лайфхаки и код для Java-разработчиков. Каждый пост — реальная польза. Учим Java на примерах.

По всем вопросам @evgenycarter
Download Telegram
🧩 Зачем в Java использовать EnumSet вместо Set<Enum>?

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

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


Set<Day> days = new HashSet<>();


Но в Java есть специализированная реализация — EnumSet, которая в десятки раз быстрее, потребляет меньше памяти и гарантирует отсутствие null.

Вот как это выглядит:


EnumSet<Day> days = EnumSet.of(Day.MONDAY, Day.WEDNESDAY);


💡 Почему EnumSet лучше:
- Под капотом реализован как битовая маска — супербыстро.
- Использует гораздо меньше памяти, чем обычный HashSet.
- Все значения в EnumSet должны быть одного enum-типа — меньше шансов ошибиться.
- null туда не добавить — меньше багов.

📌 Пример:

enum Day {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY
}

EnumSet<Day> workDays = EnumSet.range(Day.MONDAY, Day.FRIDAY);
System.out.println(workDays); // [MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY]


Если ты до сих пор не используешь EnumSet, советую обратить внимание. Особенно в перформанс-критичных задачах — это маленькая оптимизация, которая может дать большую разницу.

👉 @java_geek
В Java ошибки NoClassDefFoundError и NoSuchMethodError относятся к runtime ошибкам, возникающим в процессе выполнения программы, и обычно связаны с проблемами совместимости, загрузки классов и зависимости.


NoClassDefFoundError

💥 Причина:
JVM не может найти определение класса во время выполнения, хотя он был доступен во время компиляции.

🔍 Частые причины:
1. Класс отсутствует в classpath во время запуска.
- Например, зависимость была на этапе компиляции, но не добавлена в JAR или отсутствует в runtime classpath.

2. Исключение при инициализации класса (ExceptionInInitializerError).
- Если статический блок инициализации выбрасывает исключение, класс считается «не загруженным».

3. Разные classloaders.
- В особенно сложных системах (например, сервлеты, Spring, OSGi), разные classloader'ы могут видеть разные классы.

4. Удалён/переименован класс после компиляции.



NoSuchMethodError

💥 Причина:
JVM не может найти метод с указанной сигнатурой в классе во время выполнения.

🔍 Частые причины:
1. Метод существует во время компиляции, но изменён или удалён после:
- Например, библиотека была обновлена, и сигнатура метода изменилась.

2. Несовместимость версий библиотек:
- Одна библиотека компилируется с одной версией зависимости, а в рантайме подключена другая версия (без нужного метода).

3. Переопределение метода в наследнике может не сработать, если структура иерархии классов поменялась между компиляцией и выполнением.



Как диагностировать и решать

1. Проверить classpath:
- Используй -verbose:class при запуске JVM, чтобы увидеть, откуда загружаются классы.

2. Проверить версии зависимостей:
- Инструменты вроде mvn dependency:tree или gradle dependencies помогут выявить конфликты.

3. Проверить jar-файлы на наличие нужных классов/методов:
- Распаковать jar: jar tf your-lib.jar
- Проверить сигнатуры методов с помощью javap.

4. Избегай теневых зависимостей (shadow dependencies).

5. Используй dependency management:
- Например, в Maven зафиксировать версии зависимостей через <dependencyManagement>.


👉 @java_geek
🧠 Прокачиваем Spring Boot: как исключить лишние автоконфигурации и ускорить старт приложения

Spring Boot — мощная штука, но автоконфигурации могут подгружать тонну ненужного. Это влияет на время старта, объём памяти и даже security.

📌 Как отключить ненужное?

Используйте аннотацию @SpringBootApplication(exclude = {...})

Пример:

@SpringBootApplication(exclude = {
DataSourceAutoConfiguration.class,
SecurityAutoConfiguration.class
})
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}


💡 Подсказка: Чтобы понять, что именно подтягивается — включи дебаг логгер:


logging:
level:
org.springframework.boot.autoconfigure: DEBUG


Он покажет, какие конфигурации были включены, отключены или неактивны.

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

🧰 Альтернатива — использовать spring.factories или @EnableAutoConfiguration вручную (чаще — в библиотеках).

📈 Итог: точечный контроль над автоконфигурацией = быстрее, легче, безопаснее.

👉 @java_geek
🚀 Подборка 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
Какими свойствами обладает порождаемое equals() отношение эквивалентности?

☕️ Рефлексивность: для любой ссылки на значение x, x.equals(x) вернет true;
☕️ Симметричность: для любых ссылок на значения x и y, x.equals(y) должно вернуть true, тогда и только тогда, когда y.equals(x) возвращает true.
☕️ Транзитивность: для любых ссылок на значения x, y и z, если x.equals(y) и y.equals(z) возвращают true, тогда и x.equals(z) вернёт true;
☕️ Непротиворечивость: для любых ссылок на значения х и у, если несколько раз вызвать х.equals(y), постоянно будет возвращаться значение true либо постоянно будет возвращаться значение false при условии, что никакая информация, используемая при сравнении объектов, не поменялась.

Для любой ненулевой ссылки на значение х выражение х.equals(null) должно возвращать false.

👉 @java_geek
Ленивая инициализация бинов в Spring Boot 3.

Обычно все бины поднимаются на старте приложения. Это может тормозить загрузку, особенно если есть тяжёлые компоненты (например, коннекторы к БД или внешним сервисам).

📌 Как включить ленивую инициализацию всех бинов:


@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(MyApplication.class);
app.setLazyInitialization(true);
app.run(args);
}
}


Или через application.properties:


spring.main.lazy-initialization=true


💡 Тогда бины будут создаваться только при первом использовании, а не при старте.


⚠️ Когда стоит использовать:

- Для ускорения старта больших приложений.
- При разработке — быстрее ребилд и перезапуск.

⚠️ Когда лучше избегать:

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


🧠 Можно включать ленивую инициализацию точечно:


@Component
@Lazy
public class HeavyService {
// Поднимется только когда реально понадобится
}


👉 @java_geek
🧠 @Value — тихая ловушка Spring'а

Сегодня покажу вам, почему аннотация @Value — не лучший выбор для работы с конфигурацией, особенно в Spring Boot 3+.

Допустим, у вас такой конфиг:


@Value("${app.timeout:30}")
private int timeout;


📌 Проблема #1: Плохая валидация

Если значение в application.yaml невалидное (например, timeout: abc), приложение *упадёт при старте*, но вы получите лишь общее сообщение Failed to bind…, без точной причины.

📌 Проблема #2: Нет автокомплита

IDE не сможет подсказать, какие свойства вообще есть. Рефакторинг ключей — боль.

📌 Проблема #3: Тестирование

Труднее подменить значения в тестах: @Value не так просто "подсунуть" моками.


Современный подход — использовать @ConfigurationProperties:


@ConfigurationProperties(prefix = "app")
@Configuration
public class AppProperties {
private Duration timeout = Duration.ofSeconds(30);

// геттеры/сеттеры
}


И в application.yaml:


app:
timeout: 30s


💡 Spring сам сконвертирует 30s в Duration, поддержит автокомплит в IDE, и вы сможете валидировать значения с @Validated.

⚠️ Не забудьте включить бин:


@EnableConfigurationProperties(AppProperties.class)


📌 Резюме: @Value — для быстрых хаков. Для серьёзной конфигурации — @ConfigurationProperties.

👉 @java_geek
🧠 Проблема ленивой инициализации @Transactional-сервисов в Spring Boot

Когда вы используете @Transactional на методе сервиса, Spring оборачивает бин в прокси. Но если вы решите сделать ленивую инициализацию (@Lazy) или внедрите такой бин в другой с помощью ObjectProvider.getIfAvailable() или @Autowired(required = false) — есть риск неожиданного поведения.

📌 Типичный баг:


@Service
@Lazy
public class MyService {

@Transactional
public void doSomething() {
// ...
}
}


🔍 Если где-то в коде вызвать applicationContext.getBean(MyService.class) в момент, когда прокси ещё не создан — вы получите оригинальный, не-прокси-объект. А значит, @Transactional не сработает.

⚠️ В результате — метод выполнится без транзакции, и вы не поймёте почему.

💡 Как избежать:

* Никогда не используйте @Lazy или ленивое получение @Transactional-сервисов, если не понимаете нюансов проксирования.
* Лучше разделите логику: сервис без прокси — отдельно, бизнес-методы с @Transactional — в другом бине.

Надёжный способ: вызывать @Transactional-методы только через Spring-контейнер. Даже внутри самого сервиса — через self-injection:


@Service
public class MyService {

private final MyService self;

public MyService(@Lazy MyService self) {
this.self = self;
}

public void doWrapper() {
self.doTransactional(); // прокси работает
}

@Transactional
public void doTransactional() {
// ...
}
}


👉 @java_geek
🧠 Ленивая инициализация бинов в Spring Boot 3 — когда это спасает прод

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

📌 Как включить ленивую инициализацию глобально:


@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(App.class);
app.setLazyInitialization(true);
app.run(args);
}
}


📌 Или в application.yml:


spring:
main:
lazy-initialization: true


💡 Бины будут создаваться только при первом запросе к ним. Это уменьшает время старта и помогает "пережить" временные проблемы.

⚠️ Минусы:

* Ошибки сдвигаются с этапа запуска на runtime.
* Если бин важен для старта (например, контроллер или Scheduler), его лучше инициализировать сразу.

📌 Тонкая настройка:
Хотите ленивую инициализацию только для части приложения?


@Lazy
@Component
public class HeavyService {
// ...
}


💡 Работает и с @Bean, @Service, @Repository.

📈 Используйте в микросервисах с большим числом зависимостей или при миграции на Spring Boot 3+, где время старта стало критичным (например, в serverless-архитектуре).

👉 @java_geek
🔍Тестовое собеседование на Middle Java-разработчика завтра

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

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

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

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

Реклама. ООО "ШОРТКАТ", ИНН: 9731139396, erid: 2VtzqvEJJNG
Please open Telegram to view this post
VIEW IN TELEGRAM
🧠 Почему @Transactional не работает в private-методах?

В Spring @Transactional работает через прокси. Это значит, что Spring оборачивает бин в обёртку, которая и управляет транзакцией. Но есть важный нюанс:

📌 Прокси перехватывает только ВНЕШНИЕ вызовы метода.

Если вы вызываете @Transactional-метод изнутри того же класса, транзакция не начнётся.

Пример:


@Service
public class UserService {

public void createUser() {
// вызов внутреннего метода — транзакция не активируется
saveUser();
}

@Transactional
private void saveUser() {
// НЕ будет работать как транзакционный
}
}


💡 Даже если вы сделаете метод public, но вызов будет из того же класса — эффект тот же: Spring-прокси его не "перехватит".

⚠️ Аннотация @Transactional не работает на private-методах вообще. Прокси просто не может их подменить.

Правильный подход:
Вынесите транзакционный метод в отдельный бин:


@Service
public class UserSaver {

@Transactional
public void saveUser() {
// теперь работает!
}
}


И используйте его из другого бина:


@Service
public class UserService {
private final UserSaver userSaver;

public UserService(UserSaver userSaver) {
this.userSaver = userSaver;
}

public void createUser() {
userSaver.saveUser(); // транзакция начнётся
}
}


📌 Или используйте аспектно-ориентированную реализацию с @EnableAspectJAutoProxy(exposeProxy = true) + AopContext.currentProxy(), но это уже хардкор.

👉 @java_geek
🚀 Открой для себя идеальный путь к лидерству с карьерным тестом от ОЭЗ «Алабуга»! 🌟

Мечтаете о карьере в крупной компании, где ваш потенциал раскроется на полную? Наш тест поможет вам определить вашу уникальную лидерскую роль. Может быть, именно вы станете тем лидером, который выведет команду на новый уровень?

После прохождения теста вы можете заполнить заявку и получить приглашение на эксклюзивную лидерскую программу. Участие в программе открывает реальные перспективы трудоустройства в ОЭЗ «Алабуга», предоставляя шанс начать путь к профессиональному признанию.

Сделайте первый шаг к своему будущему сегодня! Пройдите тест, подайте заявку и начните строить свою карьеру вместе с нами. 🎯
Метод isEmpty()

isEmpty() – проверяет список на наличие элементов. Если список пустой, то возвращает true, в противном случае – false.

👉 @java_geek
Зачем нужны и какие бывают блоки инициализации?

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

• Существуют статические и нестатические блоки инициализации.
• Блок инициализации выполняется перед инициализацией класса загрузчиком классов или созданием объекта класса с помощью конструктора.
• Несколько блоков инициализации выполняются в порядке следования в коде класса.
• Блок инициализации способен генерировать исключения, если их объявления перечислены в throws всех конструкторов класса.
• Блок инициализации возможно создать и в анонимном классе.

👉 @java_geek
🔍Тестовое собеседование с Java-разработчиком из Т1 Иннотех уже завтра

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

Как это будет:
📂 Илья Аров, старший разработчик в Т1, будет задавать реальные вопросы и задачи разработчику-добровольцу
📂 Илья будет комментировать каждый ответ респондента, чтобы дать понять чего от вас ожидает собеседующий на интервью
📂 В конце можно будет задать любой вопрос Илье

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

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

Реклама. ООО "ШОРТКАТ", ИНН: 9731139396, erid: 2VtzqxFHKss
Please open Telegram to view this post
VIEW IN TELEGRAM
Collections.disjoint()

Collections.disjoint() проверяет, не имеют ли две коллекции общих элементов. Это полезно для фильтрации, сравнения и оптимизации поиска пересечений.

👉 @java_geek
Please open Telegram to view this post
VIEW IN TELEGRAM
HashMap: chain hashing и битовый спрединг

🧠 HashMap использует chain hashing + битовый спрединг

🔹 Хэш-функция (bit mixing):


int h = key.hashCode();
int hash = h ^ (h >>> 16);


🔹 Выбор бакета:


int idx = hash & (table.length - 1);


📌 Separate chaining: в каждом бакете хранится связный список (Java 8+ превращает списки длиной >8 в красно-черное дерево для ускорения).
📈 Сложность: средняя O(1), в худшем случае O(n) → O(log n) после treeification.
💡 Bit mixing объединяет старшие и младшие биты, чтобы при взятии по модулю power-of-two (маска &) распределение оставалось равномерным.
⚠️ Не для криптографии: это простая битовая операция, а не криптостойкая хэш-функция.

👉 @java_geek
🧠 Почему @Transactional не работает?

Один из самых частых вопросов: "Я поставил @Transactional, но транзакция не откатывается. Почему?"

📌 Ответ — в механизме прокси Spring.

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

💡 Пример:


@Service
public class UserService {
public void registerUser() {
createUser(); // Транзакция не работает!
}

@Transactional
public void createUser() {
// изменения в БД
}
}


📎 Решения:

1. Вынести метод в другой бин:


@Service
public class UserService {
private final UserWriter writer;

public UserService(UserWriter writer) {
this.writer = writer;
}

public void registerUser() {
writer.createUser(); // работает
}
}

@Service
public class UserWriter {
@Transactional
public void createUser() {
// изменения в БД
}
}


2. Или вызвать себя через `ApplicationContext`:


@Autowired
private ApplicationContext context;

public void registerUser() {
context.getBean(UserService.class).createUser(); // работает
}


⚠️ Но лучше использовать первый способ — он чище архитектурно.

👉 @java_geek
👩‍💻🎯 Юнитесты на Java: как новичку поймать баги за 5 Секунд?

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

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

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

О чём поговорим:
✔️ Что такое Unit-тесты? Для чего они нужны, даже если «код и так работает».
✔️ JUnit 5 для новичков: как установить и написать первый тест.
✔️ Тестирование = Дзен-кодинг: как тесты помогают понять свой код лучше вас самих.
✔️ Ловушки и лайфхаки: что делать, если тесты падают?

Кому будет интересно:
Начинающим Java-разработчикам, студентам и всем, кто хочет перестать бояться слов «тестирование» и «баги».

В результате вебинара вы:
Создадите свой первый тест на Java, поймёте, как тестировать методы с исключениями, и начнёте писать код, которым можно гордиться.

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

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