Java: fill the gaps
Привет! Меня зовут Диана, и я занимаюсь разработкой с 2013. Здесь пишу просто и понятно про джава бэк 🔥Тот самый курс по многопочке🔥 https://fillthegaps.ru/mt Комплименты, вопросы, предложения: @utki_letyat
Show more📈 Analytical overview of Telegram channel Java: fill the gaps
Channel Java: fill the gaps (@java_fillthegaps) in the Russian language segment is an active participant. Currently, the community unites 12 549 subscribers, ranking 10 121 in the Technologies & Applications category and 52 862 in the Russia region.
📊 Audience metrics and dynamics
Since its creation on невідомо, the project has demonstrated rapid growth, gathering an audience of 12 549 subscribers.
According to the latest data from 07 June, 2026, the channel demonstrates stable activity. Although there has been a change in the number of participants by -46 over the last 30 days and by 0 over the last 24 hours, overall reach remains high.
- Verification status: Not verified
- Engagement rate (ER): The average audience engagement rate is 34.72%. Within the first 24 hours after publication, content typically collects N/A% reactions from the total number of subscribers.
- Post reach: On average, each post receives 0 views. Within the first day, a publication typically gains 0 views.
- Reactions and interaction: The audience actively supports content: the average number of reactions per post is 0.
- Thematic interests: Content is focused on key topics such as redis, hashmap, linkedhashmap, индекс, фича.
📝 Description and content policy
The author describes the resource as a platform for expressing subjective opinions:
“Привет! Меня зовут Диана, и я занимаюсь разработкой с 2013. Здесь пишу просто и понятно про джава бэк
🔥Тот самый курс по многопочке🔥
https://fillthegaps.ru/mt
Комплименты, вопросы, предложения: @utki_letyat”
Thanks to the high frequency of updates (latest data received on 08 June, 2026), the channel maintains relevance and a high level of publication reach. Analytics show that the audience actively interacts with content, making it an important point of influence in the Technologies & Applications category.
public void do() {
File f=new File("t.txt");
// Создаём объект File, ресурс "t.txt" теперь наш
// что-то делаем
}
// вышли из метода: объект f уже не нужен, ресурс "t.txt" освобождается
RAII легко реализовать в С++. В конструкторе пишем логику "открытия" ресурса, а в деструкторе - "закрытия". Конструктор и деструктор явно прописываются, поэтому ЖЦ объекта и ресурса под контролем.
В java так не получится. Деструктор выполнится неизвестно когда, а ресурс - штука ценная. Поэтому в java нужно явно вызвать метод закрытия. В стандартных библиотеках это close().
В java 7 появилась специальная конструкция для ресурсов:
try (PrintWriter writer = new PrintWriter(…)) {
// что-то делаем
}
Ресурс реализует интерфейс AutoCloseable, и после завершения блока для него вызовется close(). try-with-resources считается java реализацией RAII.
Но такой формат не идеален. Внутри try всегда определяется новый объект. Когда ресурсов два и больше, код становится громоздким:
try (DatagramChannel udpServer = …;
Selector selector = …) {
// …
}
В java 9 в блок try можно передать переменные:
DatagramChannel udpServer = …;
Selector selector = …;
try (udpServer;selector) {
// …
}
С одной стороны это удобно. Код выглядит приятно.
С другой - после try остаются переменные с закрытыми ресурсами. Теперь нельзя сказать, что java реализует RAII.
Ну и ладно, никто не расстроился🙂 Языки разные, и классно замечать, как по-разному в них реализуются идеи, и как они меняются с течением времени.git stash save "stash name"В IDEA: VCS → Git → Stash Changes... Вернуть изменения на место: 🔸git stash apply "stash name" и оставить stash в локальном репозитории 🔸git stash pop "stash name" и удалить стэш В IDEA: VCS → Git → Unstash Changes... Что важно: ✅ Сохраняются ВСЕ текущие изменения в ветке ✅ Обратно применяются ВСЕ изменения в стэше ✅ Изменения хранятся в локальном git репозитории Shelve Удобная фича IDEA для сохранения части изменений: VCS → Shelve Changes... Галочками отмечаем, что сохранить. Чтобы вернуть обратно: Вкладка Git (Alt + 9 или найдите внизу) → Shelve. Отмечайте, какие изменения применить к коду. ✅ Можно выбрать, что сохранять ✅ Можно указать, что восстановить ✅ Изменения хранятся в локальном IDEA проекте
public final class State extends Enum {
public static final State NEW;
public static final State VALIDATED;
// init блок
State() {...}
// static блок
}
Возникла проблема. Перед вызовом конструктора надо закончить со статическими полями. А статические поля - экземпляры этого же класса. Замкнутый круг.
В такой ситуации JVM создаёт экземпляры NEW и VALIDATED перед статическими блоками. Получается такой порядок:
1️⃣ Создаём экземпляр State NEW:
▫️блок инициализации S-Init
▫️конструктор S-Constr
2️⃣ Повторяем тот же процесс для VALIDATED
3️⃣ Выполняем статический блок S-Static
Поэтому правильный ответ - G:
▫️enum NEW(Init-Constr)
▫️enum VALIDATED(Init-Constr)
▫️enum-Static
▫️объект User (Init-Constr)if (state == UserState.NEW) {…}
2️⃣ Паттерн Singleton
Вообще синглтон - антипаттерн и антитренд. Если без него никак - рассмотрите вариант с enum. Если вы склонны к риску, можно сделать изменяемые поля.
✅ Может быть несколько объектов в рамках одного enum
✅ Доступ из любого места в коде
✅ Ленивая инициализация
3️⃣ Паттерн State
Более продвинутый вариант, чем "набор констант". Здесь фокус на данных: используются связанные значения, а не элемент enum сам по себе.
Пример: в статус пользователя вносим дополнительные поля - необходимость подтверждения личности и максимальный размер скидки:
enum UserState {
NEW(true, 10),
VALIDATED(false, 25),
FRAUD(true, 0);
boolean needConfirmation;
int maxDiscount;
}
4️⃣ Паттерн Strategy
Здесь фокус на разнице в поведении. Абстрактный метод переопределяется для каждого экземпляра:
NEW { boolean check(Order){…}},
VALIDATED { boolean check(Order){…}};
abstract boolean check(Order order)
✅ Подойдёт для алгоритмов, конвертеров, сортировок
✅ Простая иерархия, всё в одном классе
✅ Список всех значений доступен через values()
😐 Весь код в одном файле. Не всегда удобно
❌ Сложно связать с другими объектами
❌ Нарушается принцип open for extension but closed for modification
Получается специфическая альтернатива полиморфизму, но иногда ок.
Enum - не просто набор констант. Инструмент своеобразный, но полезно знать и такие реализации паттернов. Чем шире арсенал разработчика, тем выше шанс найти подходящее решение.public final class Planet extends Enum {
public static final Planet EARTH;
public static final Planet MARS;
}
Полноценные классы c конструкторами, методами, полями и статическими элементами. У экземпляров есть состояние и определённое поведение.
Но есть нюансы:
🔸 Суперкласс Enum
От суперкласса Enum наследуются методы name(), ordinal() и статический метод values().
name() возвращает имя переменной, ordinal() - порядковый номер в списке. На практике эти методы достаточно бесполезны.
Метод values() используется чаще и возвращает массив всех объектов. Можно пройтись по нему в цикле:
for (Planet p : Planet.values()) {…}
или через Stream API:
Arrays.stream(Planet.values()).forEach(…)🔸 Интерфейсы суперкласса Enum реализует три интерфейса: Comparable, Serializable, Constable. Первые два всем знакомы. Интерфейс Constable определяет методы для размещения объектов в пуле констант внутри JVM. 🔸 Создание экземпляров Этим занимается JVM на старте приложения. Экземпляры енума создаются через приватный конструктор, недоступный вне енума. 🔸 Поля Указываются для каждого экземпляра, инициализируются в конcтрукторе:
public enum Planet {
MARS(3389),
EARTH(6371);
int radius;
Planet(int radius) {
this.radius = radius;
}
}
🔸 Два типа методов
▫️Обычные
public int getRadius()
Используется для геттеров и простых вычислений.
В теории можно сделать set* метод и поменять поле у любого экземпляра. Но на практике так никто не делает. Когда объект доступен из любого места системы, то проще жить, если он неизменяемый.
▫️Абстрактные
Каждый экземпляр определяет свою реализацию:
public enum Planet {
MARS {
int distanceFrom(int) {…}
},
EARTH {
int distanceFrom(int) {…}
};
abstract int distanceFrom(int);
}
🔸 Наследование
Любой enum - это final класс с уже определённым суперклассом. Единственный шанс встроить enum в иерархию - добавить для него интерфейс.
Иногда это удобно. Если у енумов и классов один интерфейс, то с ними можно работать через один метод:
interface SpaceObject
enum Planet implements SpaceObject
class Meteor implements SpaceObject
public void getInfo(SpaceObject so)-XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -XX:+UseJVMCICompiler map.compute(key,(key,value)->value+1)
Покрыта ветка В. Если элемента с ключом key нет, то в качестве value будет null. Велика вероятность NullPonterException
🔹 map.computeIfPresent(key,(key,value)->value+1)
Покрыта ветка Б. Нет элемента - ничего не делаем
🔹 map.merge(key,defaultValue,(oldValue,newValue) -> oldValue+1);
Покрывает ветки А и В:
▫️ Если элемента нет, добавляем (key, default)
▫️ Если элемент есть, обновляем по правилу
Итого, как сценарные ветки покрыты методами:
Ветка А: merge
Ветка Б: computeIfPresent
Ветка В: merge, compute
Все сценарии покрываются двумя методами - computeIfPresent и merge.
Метод compute в этом случае избыточен. Избыточность - ок, если метод добавляет удобства и не увеличивает вероятность ошибок. В случае compute это не так, так как появляется вероятность получения NPE.
На этом небольшом примере видно, как проверить дизайн нового API. Методы должны быть удобными, понятными и не заставлять разработчиков запоминать особые случаи.
Available now! Telegram Research 2025 — the year's key insights 
