Все ключевые слова Java в одном месте
Java содержит 53 зарезервированных ключевых слова, которые нельзя использовать как имена переменных, методов или классов — каждое из них выполняет определённую роль в языке.
Независимо от того, только ли ты начинаешь изучать Java или готовишься к собеседованию — знание этих ключевых слов обязательно
👉 Java Portal
Java содержит 53 зарезервированных ключевых слова, которые нельзя использовать как имена переменных, методов или классов — каждое из них выполняет определённую роль в языке.
Независимо от того, только ли ты начинаешь изучать Java или готовишься к собеседованию — знание этих ключевых слов обязательно
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11❤3💊1
Прокачай производительность своего Java-приложения с помощью мощного кэширования.
Узнай, как интегрировать Spring Boot, Redis и Docker в этом практическом гайде.
Читать сейчас: тык😈
👉 Java Portal
Узнай, как интегрировать Spring Boot, Redis и Docker в этом практическом гайде.
Читать сейчас: тык
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6💊1
Sealed-классы и интерфейсы в Java
Они позволяют явно контролировать, какие классы могут расширять или реализовывать тип — делая иерархии безопаснее, легче в сопровождении и идеально подходящими для исчерпывающего pattern matching'а
Начиная с Java 17, были введены sealed-классы и sealed-интерфейсы как способ ограничить и контролировать иерархию наследования.
Как это работает?
🔹 Используй модификатор
🔹 Все разрешённые подтипы должны находиться в одном модуле или пакете и обязаны быть помечены как
Зачем использовать sealed-классы и интерфейсы?
👉 Более строгая инкапсуляция и контроль над публичным API
👉 Безопасный и предсказуемый код (отлично подходит для pattern matching в
👉 Защита от нежелательного наследования или реализации
👉 Java Portal
Они позволяют явно контролировать, какие классы могут расширять или реализовывать тип — делая иерархии безопаснее, легче в сопровождении и идеально подходящими для исчерпывающего pattern matching'а
Начиная с Java 17, были введены sealed-классы и sealed-интерфейсы как способ ограничить и контролировать иерархию наследования.
Как это работает?
sealed
и ключевое слово permits, чтобы явно указать разрешённые подклассы или реализации.final
, sealed или non-sealed
Зачем использовать sealed-классы и интерфейсы?
switch
)Please open Telegram to view this post
VIEW IN TELEGRAM
👍6❤2
This media is not supported in your browser
VIEW IN TELEGRAM
Давайте разберёмся с Git Merge и Rebase
Git предоставляет два мощных инструмента для интеграции изменений из одной ветки (часто feature-ветки) в другую (обычно main):
Merge и Rebase
Оба инструмента решают одну задачу — объединение кода, но делают это по-разному.
✔️ Git Merge
Merge создаёт новый коммит, который фиксирует объединение двух веток.
В истории это видно как слияние двух независимых линий разработки в одной точке.
Шаги:
1. Переключись на целевую ветку (обычно main)
2. Выполни
Результаты:
🔸 Создаётся новый merge-коммит в целевой ветке с ссылками на родительские коммиты
🔸 История целевой ветки становится разветвлённой, отражая все слияния
🔸 Это более безопасный вариант для командной работы — история изменений сохраняется
✔️ Git Rebase
Rebase переписывает историю ветки (обычно feature-ветки), как будто коммиты были сделаны поверх другой ветки (например, main).
Получается более линейная история без merge-коммитов.
Шаги:
1. Переключись на ветку, которую хочешь ребейзнуть (например, feature)
2. Выполни
Результаты:
🔸 Коммиты из feature будут повторно применены на вершину main, создаются новые коммиты с теми же изменениями
🔸 Целевая ветка (main) при этом не изменяется
🔸 История feature-ветки становится линейной, но её история будет переписана
Примечания:
После успешного rebase, финальное merge в main часто выполняется как fast-forward, т.к. история выглядит непрерывной
Rebase изменяет ветку, на которой ты находишься, а не целевую ветку
Итог:
👉 Java Portal
Git предоставляет два мощных инструмента для интеграции изменений из одной ветки (часто feature-ветки) в другую (обычно main):
Merge и Rebase
Оба инструмента решают одну задачу — объединение кода, но делают это по-разному.
Merge создаёт новый коммит, который фиксирует объединение двух веток.
В истории это видно как слияние двух независимых линий разработки в одной точке.
Шаги:
1. Переключись на целевую ветку (обычно main)
2. Выполни
git merge <feature>
— укажи имя исходной веткиРезультаты:
Rebase переписывает историю ветки (обычно feature-ветки), как будто коммиты были сделаны поверх другой ветки (например, main).
Получается более линейная история без merge-коммитов.
Шаги:
1. Переключись на ветку, которую хочешь ребейзнуть (например, feature)
2. Выполни
git rebase <main>
Результаты:
Примечания:
После успешного rebase, финальное merge в main часто выполняется как fast-forward, т.к. история выглядит непрерывной
Rebase изменяет ветку, на которой ты находишься, а не целевую ветку
Итог:
merge
сохраняет историю как есть → хорошо для командной работыrebase
делает историю аккуратной → хорошо для чистоты, но требует осторожностиPlease open Telegram to view this post
VIEW IN TELEGRAM
❤10👍4
Базовые приёмы экономии памяти в Java
1. Ленивая инициализация "тяжёлых" полей
– Используйте lazy initialization, чтобы откладывать создание объекта до момента, когда он действительно понадобится.
2. Избегайте анонимных внутренних классов в циклах
– Каждое такое использование создаёт объект внутреннего класса — это скрытая нагрузка на память.
3. Используйте статические фабричные методы
– Они позволяют экономить память за счёт повторного использования уже созданных экземпляров, вместо создания новых при каждом вызове.
4. Применяйте метод intern()
– Метод
Используя
5. Используйте паттерн Flyweight для повторяющихся неизменяемых данных
– Экономит память за счёт разделения общих экземпляров (используется, например, в
👉 Java Portal
1. Ленивая инициализация "тяжёлых" полей
– Используйте lazy initialization, чтобы откладывать создание объекта до момента, когда он действительно понадобится.
2. Избегайте анонимных внутренних классов в циклах
– Каждое такое использование создаёт объект внутреннего класса — это скрытая нагрузка на память.
3. Используйте статические фабричные методы
– Они позволяют экономить память за счёт повторного использования уже созданных экземпляров, вместо создания новых при каждом вызове.
4. Применяйте метод intern()
– Метод
intern()
класса String возвращает каноническое представление строки.Используя
intern()
, можно гарантировать, что одна и та же строка будет представлена в памяти в виде единственного объекта, даже если она создаётся многократно.String s1 = "hello";
String s2 = "hello".intern();
5. Используйте паттерн Flyweight для повторяющихся неизменяемых данных
– Экономит память за счёт разделения общих экземпляров (используется, например, в
Integer.valueOf()
, Boolean.TRUE
и т.п.).Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8❤6
Проектирование Backend-системы. Система уведомлений
Цель —> Разработать систему для доставки уведомлений пользователям через:
➣ Встроенные уведомления
➣ Push-уведомления (мобильные/веб)
➣ Email
С поддержкой:
✓Масштабируемости (миллионы пользователей)
✓Настраиваемых пользовательских предпочтений
✓Надежности, повторных попыток и дедупликации
✓Реального времени и пакетных оповещений
Пошаговый сквозной процесс
Шаг 1: Срабатывание события
✓ Приложение инициирует событие:
➣ Например, пользователь A лайкнул ваш пост
➣ Отправляется запрос POST на API /notify:
Шаг 2: Добавление в очередь уведомлений
➣ API валидирует данные и помещает сообщение в очередь уведомлений (Kafka/RabbitMQ)
Шаг 3: Обработка воркером
✓ Воркер извлекает сообщение из очереди:
➣ Получает полную информацию о событии
➣ Обращается к сервису предпочтений:
- Подписан ли UserB на уведомления типа "like"?
- Хочет email или только in-app?
✓ Создает payload уведомления, например:
✓
Шаг 4: Рассылка по каналам
✓ На основе предпочтений воркер запускает соответствующие каналы:
➣ In-App Writer → сохраняет в БД (для отображения иконки колокольчика)
➣ Push-сервис → отправляет push (мобильный/веб) через FCM/APNs
➣ Email-сервис → ставит email в очередь (через SES/SendGrid)
Шаг 5: Отправка и повторные попытки
✓ Сервисы каналов:
➣ Декуплированы для изоляции отказов
➣ Повторяют попытки при сбоях (3–5 раз с экспоненциальной задержкой)
➣ Логируют статус (отправлено, ошибка, пропущено)
Шаг 6: Отображение in-app уведомлений
✓ UI вызывает /notifications?user=UserB
✓ Возвращаются N последних уведомлений из БД:
Функции надежности
✓ Гарантированная доставка хотя бы один раз с идемпотентной записью
✓ Повторные попытки с экспоненциальной задержкой
✓ DLQ (Dead Letter Queue) для сообщений с ошибками
✓ Метрики: успех/неудача на сообщение
✓ Алерты при переполнении очереди или всплесках ошибок
👉 Java Portal
Цель —> Разработать систему для доставки уведомлений пользователям через:
➣ Встроенные уведомления
➣ Push-уведомления (мобильные/веб)
С поддержкой:
✓Масштабируемости (миллионы пользователей)
✓Настраиваемых пользовательских предпочтений
✓Надежности, повторных попыток и дедупликации
✓Реального времени и пакетных оповещений
Пошаговый сквозной процесс
Шаг 1: Срабатывание события
✓ Приложение инициирует событие:
➣ Например, пользователь A лайкнул ваш пост
➣ Отправляется запрос POST на API /notify:
{
"event_type": "like",
"actor": "UserA",
"receiver": "UserB",
"object": "Post123"
}
Шаг 2: Добавление в очередь уведомлений
➣ API валидирует данные и помещает сообщение в очередь уведомлений (Kafka/RabbitMQ)
Шаг 3: Обработка воркером
✓ Воркер извлекает сообщение из очереди:
➣ Получает полную информацию о событии
➣ Обращается к сервису предпочтений:
- Подписан ли UserB на уведомления типа "like"?
- Хочет email или только in-app?
✓ Создает payload уведомления, например:
✓
"UserA лайкнул ваш пост 'How to scale systems'"
Шаг 4: Рассылка по каналам
✓ На основе предпочтений воркер запускает соответствующие каналы:
➣ In-App Writer → сохраняет в БД (для отображения иконки колокольчика)
➣ Push-сервис → отправляет push (мобильный/веб) через FCM/APNs
➣ Email-сервис → ставит email в очередь (через SES/SendGrid)
Шаг 5: Отправка и повторные попытки
✓ Сервисы каналов:
➣ Декуплированы для изоляции отказов
➣ Повторяют попытки при сбоях (3–5 раз с экспоненциальной задержкой)
➣ Логируют статус (отправлено, ошибка, пропущено)
Шаг 6: Отображение in-app уведомлений
✓ UI вызывает /notifications?user=UserB
✓ Возвращаются N последних уведомлений из БД:
[
{ "text": "UserA лайкнул ваш пост", "read": false, ... }
]
Функции надежности
✓ Гарантированная доставка хотя бы один раз с идемпотентной записью
✓ Повторные попытки с экспоненциальной задержкой
✓ DLQ (Dead Letter Queue) для сообщений с ошибками
✓ Метрики: успех/неудача на сообщение
✓ Алерты при переполнении очереди или всплесках ошибок
Please open Telegram to view this post
VIEW IN TELEGRAM
❤8👍3🔥3
Хаки Java-кодинга, которые стоит знать разработчикам
✓ Используйте
➣ Почему: короче, безопаснее, неизменяемо — снижает риск случайной мутации.
✓ Используйте
➣ Почему: устраняет проверки на
✓ Используйте
➣ Почему: чище и удобнее для сериализации/десериализации enum'ов в API, БД или файлах.
✓ Используйте
➣ Почему: читаемо, понятно, без ошибок в условных сравнениях.
✓ Используйте
➣ Почему: выразительнее и чище — больше никаких ручных
👉 Java Portal
✓ Используйте
Map.ofEntries()
для создания неизменяемых мап с несколькими парами➣ Почему: короче, безопаснее, неизменяемо — снижает риск случайной мутации.
✓ Используйте
Optional.map().orElse()
вместо ручной обработки null
➣ Почему: устраняет проверки на
null
, читается лучше, легко комбинируется с другой логикой.✓ Используйте
Enum.valueOf()
+ name()
для безопасного преобразования enum
➣ Почему: чище и удобнее для сериализации/десериализации enum'ов в API, БД или файлах.
✓ Используйте
Comparator.comparing().thenComparing()
вместо кастомной логики➣ Почему: читаемо, понятно, без ошибок в условных сравнениях.
✓ Используйте
Optional.ifPresentOrElse()
вместо if-else
с isPresent()
➣ Почему: выразительнее и чище — больше никаких ручных
get()
и нагромождений if-else
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍18❤2
Некоторые редкие, но ценные паттерны в Java
1. Null Object Pattern (Объект-Заглушка вместо null)
❯ Позволяет избежать проверок на null, возвращая объект с "пустым" поведением, реализующий ожидаемый интерфейс.
❯ Помогает держать код чистым, без множества
❯ Используй, когда возврат
2. Parameter Object Pattern (Объект параметров)
❯ Объединяет логически связанные параметры в один объект.
❯ Такой объект удобно прокидывать через разные уровни приложения, обеспечивая согласованность.
❯ Используй, когда у метода слишком много связанных аргументов.
3. Fluent Interface / Method Chaining (Флюент-интерфейс / Цепочка вызовов)
❯ Позволяет вызывать методы цепочкой, улучшая читаемость и выражая намерение кода (особенно в билдерах и конфигурациях).
❯ Используй в билдерах или для декларативной настройки.
4. Execute Around Method Pattern (Шаблон обёртки вокруг действия)
❯ Инкапсулирует логику подготовки и завершения вокруг основного действия.
❯ Гарантирует корректное освобождение ресурсов.
❯ Используй для управления ресурсами (файлы, БД и т.п.).
5. Initialization-on-Demand Holder (ленивый Singleton без
❯ Безопасный, потокобезопасный и производительный способ ленивой инициализации Singleton'а без явной синхронизации.
❯ Используй, если нужен быстрый и потокобезопасный синглтон.
👉 Java Portal
1. Null Object Pattern (Объект-Заглушка вместо null)
❯ Позволяет избежать проверок на null, возвращая объект с "пустым" поведением, реализующий ожидаемый интерфейс.
❯ Помогает держать код чистым, без множества
if (obj != null)
перед каждым вызовом метода.❯ Используй, когда возврат
null
приводит к захламлению условными конструкциями.2. Parameter Object Pattern (Объект параметров)
❯ Объединяет логически связанные параметры в один объект.
❯ Такой объект удобно прокидывать через разные уровни приложения, обеспечивая согласованность.
❯ Используй, когда у метода слишком много связанных аргументов.
3. Fluent Interface / Method Chaining (Флюент-интерфейс / Цепочка вызовов)
❯ Позволяет вызывать методы цепочкой, улучшая читаемость и выражая намерение кода (особенно в билдерах и конфигурациях).
❯ Используй в билдерах или для декларативной настройки.
4. Execute Around Method Pattern (Шаблон обёртки вокруг действия)
❯ Инкапсулирует логику подготовки и завершения вокруг основного действия.
❯ Гарантирует корректное освобождение ресурсов.
❯ Используй для управления ресурсами (файлы, БД и т.п.).
5. Initialization-on-Demand Holder (ленивый Singleton без
synchronized
)❯ Безопасный, потокобезопасный и производительный способ ленивой инициализации Singleton'а без явной синхронизации.
❯ Используй, если нужен быстрый и потокобезопасный синглтон.
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
❤10👍4🔥1