fa
Feedback
Java Geek

Java Geek

رفتن به کانال در Telegram

Практичные советы, лайфхаки и код для Java-разработчиков. Каждый пост — реальная польза. Учим Java на примерах. По всем вопросам @evgenycarter

نمایش بیشتر
2 449
مشترکین
اطلاعاتی وجود ندارد24 ساعت
+27 روز
+530 روز
آرشیو پست ها
🔴 Завтра тестовое собеседование с Java-разработчиком 21 января(уже завтра!) в 19:00 по мск приходи онлайн на открытое собесе
🔴 Завтра тестовое собеседование с Java-разработчиком 21 января(уже завтра!) в 19:00 по мск приходи онлайн на открытое собеседование, чтобы посмотреть на настоящее интервью на Middle Java-разработчика. Как это будет: 📂 Сергей Чамкин, старший разработчик из Uzum, ex-WildBerries, будет задавать реальные вопросы и задачи разработчику-добровольцу 📂 Cергей будет комментировать каждый ответ респондента, чтобы дать понять чего от вас ожидает собеседующий на интервью 📂 В конце можно будет задать любой вопрос Сергею Это бесплатно. Эфир проходит в рамках менторской программы от ШОРТКАТ для Java-разработчиков, которые хотят повысить свой грейд, ЗП и прокачать скиллы. Переходи в нашего бота, чтобы получить ссылку на эфир → @shortcut_sh_bot Реклама. О рекламодателе.

☕️ Java Tips: Инициализация карты в одну строку с Map.of() Помните, как раньше приходилось создавать Map с заранее известными значениями? Куча вызовов .put(), статические блоки или (не дай бог) двойные фигурные скобки. Начиная с Java 9, у нас есть красивый и лаконичный способ - Map.of(). Разберем, как это работает и, главное, чего нельзя делать. 🆚 До и После Как было раньше (The Old Way):

Map<String, Integer> map = new HashMap<>();
map.put("One", 1);
map.put("Two", 2);
map.put("Three", 3);
// Результат: много строк кода ради простых данных

Как сейчас (The Modern Way):

Map<String, Integer> map = Map.of(
    "One", 1,
    "Two", 2,
    "Three", 3
);
// Результат: чисто, читаемо, одна инструкция

⚠️ Важные нюансы (Gotchas) Использование Map.of() - это не просто синтаксический сахар для HashMap. Это создание неизменяемой (Immutable) структуры. 1. Нельзя менять данные Попытка добавить или удалить элемент приведет к ошибке.

var colors = Map.of("Red", "#FF0000");
colors.put("Blue", "#0000FF"); 
// ❌ Ошибка: UnsupportedOperationException

2. Никаких null В отличие от HashMap, здесь нельзя использовать null ни в ключах, ни в значениях.

Map.of("Key", null); 
// ❌ Ошибка: NullPointerException

3. Лимит в 10 пар Метод Map.of() перегружен для приема до 10 пар ключ-значение. Если нужно больше, используйте Map.ofEntries():

Map.ofEntries(
    Map.entry("k1", "v1"),
    Map.entry("k2", "v2"),
    // ... хоть 100 пар
    Map.entry("k100", "v100")
);

🚀 Когда использовать? Идеально подходит для конфигураций, статических словарей, тестовых данных и справочников, которые не меняются во время работы программы. #Java #CodeTips #Programming #Java9 👉 @java_geek

📌 Декоратор в Java: Как добавить логику без изменения кода? 🔹 Когда использовать? - Когда нужно добавить поведение к объекту динамически. - Когда нельзя или не хочется менять исходный код класса. - Когда необходимо сохранить принцип открытости/закрытости (OCP из SOLID). 🔹 Как это работает? Декоратор — это обёртка вокруг базового объекта. Он реализует тот же интерфейс, но внутри может добавлять новую логику. ✅ Пример использования Допустим, у нас есть базовый интерфейс Notifier, который отправляет уведомления:

public interface Notifier {
    void send(String message);
}
И его простая реализация:

public class BasicNotifier implements Notifier {
    @Override
    public void send(String message) {
        System.out.println("Отправка сообщения: " + message);
    }
}
Теперь добавим декораторы, которые расширяют функциональность: 1️⃣ Декоратор для отправки в Slack:

public class SlackNotifierDecorator implements Notifier {
    private final Notifier wrapped;

    public SlackNotifierDecorator(Notifier wrapped) {
        this.wrapped = wrapped;
    }

    @Override
    public void send(String message) {
        wrapped.send(message); // вызываем базовый метод
        System.out.println("Дополнительно отправляем в Slack: " + message);
    }
}
2️⃣ Декоратор для отправки в Email:

public class EmailNotifierDecorator implements Notifier {
    private final Notifier wrapped;

    public EmailNotifierDecorator(Notifier wrapped) {
        this.wrapped = wrapped;
    }

    @Override
    public void send(String message) {
        wrapped.send(message);
        System.out.println("Дополнительно отправляем Email: " + message);
    }
}
🚀 Использование:

public class Main {
    public static void main(String[] args) {
        Notifier notifier = new BasicNotifier();
        notifier = new SlackNotifierDecorator(notifier);
        notifier = new EmailNotifierDecorator(notifier);

        notifier.send("Привет, мир!");
    }
}
🔥 Что произойдет?

Отправка сообщения: Привет, мир!
Дополнительно отправляем в Slack: Привет, мир!
Дополнительно отправляем Email: Привет, мир!
🎯 Итог: ✅ Мы не изменяли код BasicNotifier, но добавили новую функциональность. ✅ Гибкость: можем легко комбинировать декораторы в любом порядке. ✅ Код остаётся чистым и расширяемым. 👉 @java_geek

🔴 Завтра тестовое собеседование с Java-разработчиком 24 декабря(уже завтра!) в 19:00 по мск приходи онлайн на открытое собес
🔴 Завтра тестовое собеседование с Java-разработчиком 24 декабря(уже завтра!) в 19:00 по мск приходи онлайн на открытое собеседование, чтобы посмотреть на настоящее интервью на Middle Java-разработчика. Как это будет: 📂 Сергей Чамкин, старший разработчик из Uzum, ex-WildBerries, будет задавать реальные вопросы и задачи разработчику-добровольцу 📂 Cергей будет комментировать каждый ответ респондента, чтобы дать понять чего от вас ожидает собеседующий на интервью 📂 В конце можно будет задать любой вопрос Сергею Это бесплатно. Эфир проходит в рамках менторской программы от ШОРТКАТ для Java-разработчиков, которые хотят повысить свой грейд, ЗП и прокачать скиллы. Переходи в нашего бота, чтобы получить ссылку на эфир → @shortcut_sh_bot Реклама. О рекламодателе.

☕️ Лямбды и Функциональные интерфейсы: Как это работает под капотом? Мы все любим лямбды в Java за краткость. Но задумывались ли вы, как строго типизированная Java понимает запись x -> x * 2, не зная типа переменной x? Все дело в Функциональных интерфейсах. Давайте разберем механику, которая превращает "бойлерплейт" в элегантный код. 🧩 Что такое SAM? В основе лежит концепция SAM (Single Abstract Method). Функциональный интерфейс - это интерфейс, у которого есть ровно один абстрактный метод. Лямбда-выражение - это не самостоятельный объект. Это ленивая реализация этого самого единственного метода "на лету". 🔥 До vs После Взгляните, как функциональный интерфейс Predicate<T> убивает лишний шум:

// ❌ До Java 8 (Анонимный класс)
// Куча лишнего кода ради одной проверки
Predicate<String> isLong = new Predicate<String>() {
    @Override
    public boolean test(String s) {
        return s.length() > 5;
    }
};

// ✅ С Лямбдой
// Компилятор видит Predicate -> ищет метод test -> подставляет логику
Predicate<String> isLong = s -> s.length() > 5;

⚙️ Магия invokedynamic Многие думают, что лямбда - это просто "сахар" для анонимных классов. Это не так! 💜 Анонимный класс создает реальный .class файл на диске при компиляции. 💜 Лямбда использует инструкцию байт-кода invokedynamic. Она связывает метод динамически только когда это нужно. 👉 Итог: Меньше мусора в памяти и быстрее загрузка приложения. 📚 Шпаргалка: "Великолепная четверка" В java.util.function есть интерфейсы на все случаи жизни. Запомните базу: 1. Predicate<T>boolean 💜 Суть: Проверка условия (фильтры). 💜 Пример: stream().filter(x -> x > 0) 2. Consumer<T>void 💜 Суть: Потребитель. Что-то делает с объектом, ничего не возвращая. 💜 Пример: list.forEach(System.out::println) 3. Function<T, R>R 💜 Суть: Преобразователь. Берет T, возвращает R. 💜 Пример: stream().map(User::getName) 4. Supplier<T>T 💜 Суть: Поставщик. Ничего не принимает, отдает объект. 💜 Пример: Optional.orElseGet(() -> new User()) 💡Всегда ставьте аннотацию @FunctionalInterface над своими интерфейсами. Это защитит от случайного добавления второго абстрактного метода, который сломает все лямбды в проекте. 👉 @java_geek

🔍 Завтра тестовое собеседование с Java-разработчиком 17 декабря(уже завтра!) в 19:00 по мск приходи онлайн на открытое собес
🔍 Завтра тестовое собеседование с Java-разработчиком 17 декабря(уже завтра!) в 19:00 по мск приходи онлайн на открытое собеседование, чтобы посмотреть на настоящее интервью на Middle Java-разработчика. Как это будет: 📂 Сергей Чамкин, старший разработчик из Uzum, ex-WildBerries, будет задавать реальные вопросы и задачи разработчику-добровольцу 📂 Cергей будет комментировать каждый ответ респондента, чтобы дать понять чего от вас ожидает собеседующий на интервью 📂 В конце можно будет задать любой вопрос Сергею Это бесплатно. Эфир проходит в рамках менторской программы от ШОРТКАТ для Java-разработчиков, которые хотят повысить свой грейд, ЗП и прокачать скиллы. Переходи в нашего бота, чтобы получить ссылку на эфир → @shortcut_sh_bot Реклама. О рекламодателе.

🚀 Hibernate: Эффективное обновление с @DynamicUpdate Часто ли вы задумывались, почему Hibernate при обновлении одного поля в сущности генерирует SQL-запрос, который включает все поля? Это может быть неэффективно, особенно для сущностей с десятками колонок. Именно здесь на помощь приходит аннотация @DynamicUpdate! 💡 В чем проблема? (Без @DynamicUpdate) По умолчанию, когда вы вызываете repository.save(entity) для существующей сущности, Hibernate генерирует UPDATE запрос, который устанавливает значения для всех полей, кроме первичного ключа.

// Without @DynamicUpdate
update employee
set
    age=?, // даже если только age изменился
    first_name=?, //... и это тоже
    last_name=?
where
    id=?
Если изменилось только age, остальные поля обновляются на те же значения, что были. ✨ Решение: @DynamicUpdate(true) Если вы добавите @DynamicUpdate к вашей сущности, Hibernate будет генерировать SQL-запрос UPDATE, который включает только те поля, которые были изменены (dirty-checking) с момента загрузки или создания сущности. Смотрим на код:

@Entity
@DynamicUpdate // ✨ Добавляем эту аннотацию!
public class Employee extends AbstractPersistable<Long> {
    @Column
    String firstName;

    @Column
    String lastName;

    @Column
    Integer age;
    // ...
}

// В EmployeeService:
// var entity = employeeRepository.findById(1L).get();
// entity.setAge(22); // Изменили только возраст
// employeeRepository.save(entity);
Сгенерированный SQL:

// With @DynamicUpdate
update employee
set
    age=? // ✅ Обновляется ТОЛЬКО измененное поле
where
    id=?
⚖️ Когда использовать? - Используйте, если у вас большие сущности (много колонок) и вы часто обновляете только небольшую часть полей. Это сэкономит трафик и немного ускорит базу данных. - Имейте в виду, что Hibernate придется динамически строить SQL-запрос при каждом обновлении, что может добавить небольшой оверхед, но обычно выгода от оптимизации SQL его перевешивает. Сделайте ваш код более чистым и эффективным! 🛠️ ❓ А вы используете @DynamicUpdate в своих проектах? Поделитесь в комментариях! 👇 P.S. Не путайте с @DynamicInsert, который делает то же самое для INSERT запросов (включает только не-null поля). 👉 @java_geek

Что такое пул строк? Это набор строк, хранящийся в Heap. ☕ Пул строк возможен благодаря неизменяемости строк в Java и реализации идеи интернирования строк; ☕ Пул строк помогает экономить память, но по этой же причине создание строки занимает больше времени; ☕ Когда для создания строки используются ", то сначала ищется строка в пуле с таким же значением, если находится, то просто возвращается ссылка, иначе создается новая строка в пуле, а затем возвращается ссылка на неё; ☕ При использовании оператора new создаётся новый объект String. Затем при помощи метода intern() эту строку можно поместить в пул или же получить из пула ссылку на другой объект String с таким же значением; ☕ Пул строк является примером паттерна «Приспособленец» (Flyweight). 👉 @java_geek

🔍Тестовое собеседование с ТехЛидом из МТС уже завтра 3 декабря(уже завтра!) в 19:00 по мск приходи онлайн на открытое собесе
🔍Тестовое собеседование с ТехЛидом из МТС уже завтра 3 декабря(уже завтра!) в 19:00 по мск приходи онлайн на открытое собеседование, чтобы посмотреть на настоящее интервью на Middle Java-разработчика. Как это будет: 📂 Илья Аров, старший разработчик в МТС, будет задавать реальные вопросы и задачи разработчику-добровольцу 📂 Илья будет комментировать каждый ответ респондента, чтобы дать понять чего от вас ожидает собеседующий на интервью 📂 В конце можно будет задать любой вопрос Илье Это бесплатно. Эфир проходит в рамках менторской программы от ШОРТКАТ для Java-разработчиков, которые хотят повысить свой грейд, ЗП и прокачать скиллы. Переходи в нашего бота, чтобы получить ссылку на эфир → @shortcut_sh_bot Реклама. О рекламодателе.

Что не так с кодом? Он не скомпилируется. Это вопрос на знание иерархии исключений: FileNotFoundException унаследован от IOEx
Что не так с кодом? Он не скомпилируется. Это вопрос на знание иерархии исключений: FileNotFoundException унаследован от IOException, первый catch будет перехватывать все исключения, а в следующий блок catch управление передано не будет. Поэтому возникнет ошибка: exception FileNotFoundException has already been caught. 👉 @java_geek

О чем говорит ключевое слово throws? Ответ: Модификатор throws прописывается в заголовке метода и указывает на то, что метод потенциально может выбросить исключение с указанным типом. 👉 @java_geek

Блиц-опрос Scala-разработчиковсамые полезные и бесполезные вещи в работе Смотрите подкаст «Криптонит говорит» о Scala! В нём айтишники обсуждают: 🔹Scala, Java и их перспективы; 🔹как успешно пройти собеседование в айти; 🔹что нужно делать, чтобы стать хорошим программистом; 🔹и когда нейросети смогут делать code review на уровне старшего разработчика и многое другое. 📺 VK Видео 📺 YouTube 📺 Rutube 💬 Подкаст в телеграме 🎵 Яндекс.Музыка Смотрите и подписывайтесь на подкаст «Криптонит говорит» — обсуждаем айти, искусственный интеллект, языки программирования и криптографию. Реклама АО НПК «Криптонит» ИНН 9701115253, erid: 2VtzqveAsgd

پیام ویدیو01:00

Что такое «сессия»? Сессия — это сеанс связи между клиентом и сервером, устанавливаемый на определенное время. Сеанс устанавливается непосредственно между клиентом и веб-сервером в момент получения первого запроса к веб-приложению. Каждый клиент устанавливает с сервером свой собственный сеанс, который сохраняется до окончания работы с приложением. 👉 @java_geek

«Мы поняли, что мы как Тринити и Морфеус. Нам нужен был Нео». Как ночной портье за 3 месяца разобрался в инжиниринге данных Смотрите подкаст «Криптонит говорит» о дата-инженерах! В нём эксперты оюсуждают: 🔹достигла ли пика профессия дата-инженера; 🔹какой стек нужно знать дата-инженерам; 🔹какие намечаются тренды отрасли. 📺 YouTube 📺 Rutube 💙 VK видео 💬 Подкаст в телеграме 🎵 Яндекс.Музыка Смотрите и подписывайтесь на подкаст «Криптонит говорит» — обсуждаем айти, искусственный интеллект, языки программирования и криптографию. Реклама. ООО «Агентство интернет-маркетинга "Ви 8"», ОГРН 1102468051333, erid: 2VtzqveAsgd

پیام ویدیو00:51

Что такое Local Variable? Популярный вопрос на собеседовании Java-разработчика. Local variable — это переменная, которая опре
Что такое Local Variable? Популярный вопрос на собеседовании Java-разработчика. Local variable — это переменная, которая определена внутри метода и существует вплоть до того момента, пока выполняется этот метод. Как только выполнение закончится, локальная переменная перестанет существовать. Вот программа, которая использует локальную переменную helloMessage в методе main(). 👉 @java_geek

Зачем нужен HashMap, если есть Hashtable? ☕ Методы класса Hashtable синхронизированы, что приводит к снижению производительности, а HashMap - нет; ☕ HashTable не может содержать элементы null, тогда как HashMap может содержать один ключ null и любое количество значений null; ☕ Iterator у HashMap, в отличие от Enumeration у HashTable, работает по принципу «fail-fast» (выдает исключение при любой несогласованности данных). Hashtable это устаревший класс и его использование не рекомендовано. 👉 @java_geek

🔍 Завтра тестовое собеседование с Java-разработчиком 19 ноября(уже завтра!) в 19:00 по мск приходи онлайн на открытое собесе
🔍 Завтра тестовое собеседование с Java-разработчиком 19 ноября(уже завтра!) в 19:00 по мск приходи онлайн на открытое собеседование, чтобы посмотреть на настоящее интервью на Middle Java-разработчика. Как это будет: 📂 Сергей Чамкин, старший разработчик из Uzum, ex-WildBerries, будет задавать реальные вопросы и задачи разработчику-добровольцу 📂 Cергей будет комментировать каждый ответ респондента, чтобы дать понять чего от вас ожидает собеседующий на интервью 📂 В конце можно будет задать любой вопрос Сергею Это бесплатно. Эфир проходит в рамках менторской программы от ШОРТКАТ для Java-разработчиков, которые хотят повысить свой грейд, ЗП и прокачать скиллы. Переходи в нашего бота, чтобы получить ссылку на эфир → @shortcut_sh_bot Реклама. О рекламодателе.

Расскажите о различиях вложенных классов: простых и статических? Простые вложенные классы используются для тесной связи с внешним классом, а статические — когда нужно логически сгруппировать некоторый функционал. Основные различия: - Простой вложенный класс имеет доступ к членам внешнего класса, статический - нет. - Для создания экземпляра простого вложенного класса нужен экземпляр внешнего класса, для статического - нет. - Простой вложенный класс зависит от экземпляра внешнего класса, статический - нет. 👉 @java_geek