Java: fill the gaps
Привет! Меня зовут Диана, и я занимаюсь разработкой с 2013. Здесь пишу просто и понятно про джава бэк 🔥Тот самый курс по многопочке🔥 https://fillthegaps.ru/mt Комплименты, вопросы, предложения: @utki_letyat
Ko'proq ko'rsatish📈 Telegram kanali Java: fill the gaps analitikasi
Java: fill the gaps (@java_fillthegaps) Rus til segmentidagi kanali faol ishtirokchi. Hozirda hamjamiyat 12 548 obunachidan iborat bo'lib, Texnologiyalar & Aralashmalar toifasida 10 113-o'rinni va Rossiya mintaqasida 52 819-o'rinni egallagan.
📊 Auditoriya ko‘rsatkichlari va dinamika
невідомо sanasidan buyon loyiha tez o‘sib, 12 548 obunachiga ega bo‘ldi.
08 Iyun, 2026 dagi oxirgi ma’lumotlarga ko‘ra kanal barqaror faollikka ega. Oxirgi 30 kunda obunachilar soni -43 ga, so‘nggi 24 soatda esa -3 ga o‘zgardi va umumiy qamrov yuqori darajada qolmoqda.
- Tasdiqlash holati: Tasdiqlanmagan
- Jalb etish (ER): Auditoriya o‘rtacha 34.73% darajada jalb etiladi. Nashrdan keyingi dastlabki 24 soatda kontent odatda umumiy obunachilar sonining N/A% ini tashkil etuvchi reaksiyalarni to‘playdi.
- Post qamrovi: Har bir post o‘rtacha 0 marta ko‘riladi; birinchi sutkada odatda 0 ta ko‘rish yig‘iladi.
- Reaksiyalar va o‘zaro ta’sir: Auditoriya faol: har bir postga o‘rtacha 0 ta reaksiya keladi.
- Tematik yo‘nalishlar: Kontent redis, hashmap, linkedhashmap, индекс, фича kabi asosiy mavzularga jamlangan.
📝 Tavsif va kontent siyosati
Muallif resursni shaxsiy fikrni ifoda etish maydoni sifatida ta’riflaydi:
“Привет! Меня зовут Диана, и я занимаюсь разработкой с 2013. Здесь пишу просто и понятно про джава бэк
🔥Тот самый курс по многопочке🔥
https://fillthegaps.ru/mt
Комплименты, вопросы, предложения: @utki_letyat”
Yuqori yangilanish chastotasi (oxirgi ma’lumot 09 Iyun, 2026 da olingan) sababli kanal doimo dolzarb va katta qamrovli bo‘lib qoladi. Analitika auditoriya kontent bilan faol hamkorlik qilishini, uni Texnologiyalar & Aralashmalar toifasidagi muhim ta’sir nuqtasiga aylantirishini ko‘rsatadi.
// givenИнициализация переменных и моков.
// whenВызов проверяемого метода.
// thenПроверка результата и состояния других объектов. 3 блока должны чётко следовать друг за другом, тогда тест легко читать. Если после блока проверок идёт действие и дополнительные проверки — значит тест слишком большой. 2️⃣ Что такое TDD? Test Driven Development - процесс разработки, когда сначала пишется тест, а потом код. Подробно это выглядит так: ▫️Написать тест для кода, которого нет ▫️Запустить тесты, новый тест падает ▫️Написать код, чтобы тест проходил ▫️Запустить тесты, тесты проходят ▫️Рефакторинг нового кода ▫️Запустить тесты, тесты проходят Плюсы TDD: ➕Код сразу покрыт тестами ➕У класса удобный интерфейс, который сразу используется в тестах ➕Структурированный код После этого следует такой диалог: - А Вы лично используете TDD? - Нет. - Почему? У него же столько плюсов. - Большой минус - частое переключение контекста и фокус на деталях. Мне удобнее написать простое рабочее решение, и только потом добавить проверки, валидацию и обработку ошибок. После этого в соответствии с требованиями как следует оттестировать то, что получилось. Я сразу пишу код, который легко использовать и тестировать, поэтому TDD меня только замедляет. - Согласен.
class Программист {
void написатьКод()
void помытьПосуду()
void погладитьКота()
}
Идеальная сущность с точки зрения Cohesion - лямбда-выражение. Их легко читать, тестировать и переиспользовать.
2️⃣ Связанность (Coupling)
Показывает, как одна сущность взаимодействует с другими. Класс А связан с классом Б, если в классе А
▫️Поля класса Б
▫️Вызов методов класса Б
▫️Локальные переменные класса Б
▫️Если класс А - подкласс Б
В большинстве проектов есть модуль base или common - часто он является примером сильной связанности. Менять такой модуль - всегда большой риск.
3️⃣ Сложность (Complexity)
На этот показатель влияет:
▪️Сколько сущностей взаимодействуют
▪️Количество операций в методе
▪️Глубина наследования
▪️Количество ветвлений и возможных состояний
Показатель сложности часто идёт рука об руку с размером, но не всегда. Сложный метод может быть небольшим по размеру, но скрывать внутри себя десятки вариантов развития событий:
public void check(long id) {
dao.get(id).findProcessor()
.getAccount().checkBalance();
}
4️⃣ Размер (Size)
Большие сущности сложно поддерживать. В этой категории много метрик, например, количество:
🔹Полей
🔹Методов
🔹Статических методов
🔹Подклассов
🔹Связанных библиотек
А теперь ответы на вопросы перед постом:
✅ Если класс А часто использует класс Б, то это признак высокой связанности. Связанность (coupling) характеризует внешние отношения между сущностями. Связность (cohesion) - про внутреннюю структуру самой сущности.
✅ На сложность влияет количество ветвлений и глубина наследования. Остальные характеристики относятся к категории "размер".// TODO добавить тестыТакие комментариии будут отображаться в окне TODO внизу экрана. Через него можно перейти в нужное место кода в один клик. Открыть список можно через ▫️Alt+6 ▫️View→Tool Windows→TODO Помимо стандартных TODO и FIXME можно добавить свои метки, например, OPTIMIZE, ASK, TEST. Сделать это можно в File →Settings→ Editor→ TODO.
Runnable r=() -> …
❌ Runnable r=new Runnable{
@Override
public void run(){…}
}
2️⃣ Определите сценарии использования ФИ.
ФИ — это интерфейс, но с одним абстрактным методом. В него можно добавить сколько угодно методов с реализацией — дефолтных, приватных и статических. Один ФИ может расширять другой ФИ. Класс может реализовать ФИ через implements.
Чтобы код был простым и понятным, нужно разграничивать его компоненты:
🔸Цель обычного интерфейса - обозначить набор методов для будущих классов.
🔸Цель ФИ — передать набор инструкций через лямбды и ссылки на методы.
Один метод в ФИ - оптимальный вариант. Но есть случаи, когда дополнительные методы уместны, так как тесно связаны с самим интерфейсом.
Пример: интерфейс Predicate. Несмотря на то, что он функциональный, в нём есть 4 метода с заданной реализацией: and, or, isEqual и negate.
3️⃣ Используйте аннотацию FunctionalInterface.
Она не обязательна, но облегчает чтение кода.
4️⃣ Если используете ФИ как аргумент, отражайте тип ФИ в названии метода.
Пример: в классе 2 метода с одним именем и разными типами аргументов:
void adapt(Callable) void adapt(Supplier)Этот код компилируется, но у него 2 недостатка: ▪️Чтобы понять разницу между методами нужно читать код или документацию. ▪️В качестве аргумента нельзя передать лямбда-выражение, т.к оно подходит под оба типа:
❌ adapt(str->print(str))Чтобы избежать этих проблем, используйте разные имена для методов. Хороший пример — класс CompletableFuture для многоэтапных вычислений. В его методах легко ориентироваться благодаря удачным названиям:
▫️thenAccept(Consumer)
▫️thenApply(Function)
▫️thenRun(Runnable)@FunctionalInterface
public interface Archiver{
void archive(String file)
throws FileNotFoundEx;
}
Экземплярами ФИ могут быть:
🔸Лямбда-выражение
🔸Ссылка на метод
🔸Ссылка на конструктор
Для большинства задач подойдут стандартные интерфейсы из пакета java.util.function. Всего их 43, но можно выделить 5 групп:
1️⃣ Consumer (потребитель)
Метод принимает один параметр и ничего не возвращает.
Consumer<String> c = System.out::println;2️⃣ Supplier (поставщик) Ничего не принимает, но возвращает значение.
Supplier<List> s = ArrayList::new;3️⃣ Function Принимает один параметр, возвращает одно значение:
Function<String,Long> map = s -> Long.valueOf(s);4️⃣ UnaryOperator Метод принимает один параметр и возвращает значение того же типа:
UnaryOperator<Integer> inc = i -> i+1;5️⃣ Predicate Принимает аргумент и возвращает boolean значение.
Predicate<String> filter =
s -> !s.isEmpty()
&& !s.contains("q");
У этих ФИ есть удобные вариации:
🔹BiConsumer, BiFunction, BiPredicate, BinaryOperator принимают два аргумента:
BiConsumer<Integer,Integer> b = (x,y) -> println(x+y);🔹LongFunction, LongSupplier , ToLongFunction и т.д позволяют не прописывать типы аргументов или выходных значений:
LongFunction<String> to = Long::toString;Ответ на вопрос перед постом: Интерфейс становится функциональным если в нём есть один абстрактный метод. Все остальные свойства у него такие же, как у обычного интерфейса. Аннотация FunctionalInterface не обязательна, но желательна для понимания кода.
interface Adapter {
default int get() {…}
}
Класс, который реализует интерфейс, переопределяет такой метод при необходимости.
❓Зачем нужны такие методы?
1️⃣ Облегчить изменения API
Во времена java 7 интерфейсы содержали только определения методов:
interface Collection<Т> {
void add(Т);
Т get();
}
Чтобы добавить, удалить или поменять сигнатуру метода нужно одновременно поменять код со стороны пользователей интерфейса и во всех реализациях. В рамках одного проекта это несложно, но для библиотек это сложная задача. Пользователи могут столкнутся с проблемами совместимости при переходе на новую версию.
Задача дефолтных методов - сгладить этот процесс и предоставить приемлемую или временную альтернативу.
2️⃣ Вспомогательные методы
Те методы, которые не входят в прямую функциональность интерфейса - методы для мониторинга, логгирования и т.д. Используйте с осторожностью, этот приём может нарушать принцип Interface segregation.
3️⃣ Комбинации базовых методов
В интерфейсе объявляется минимально необходимый набор методов, а некоторые методы являются просто их комбинациями. Мы обсуждали этот случай в прошлом посте. Такой "удобный" метод можно добавить в интерфейс как статический.
Статические методы вызываются через имя интерфейса и недоступны у экземпляров. Если это неудобно, оформите метод как метод по умолчанию.
Пример: интерфейс Comparator.
Основная функция — сравнение объектов через метод compare, индивидуальный для каждого класса. Цепочка из 2 компараторов - это 2 вызова compare и объединение результатов. Логика всегда одинакова, и нет смысла дублировать её в каждом подклассе:
default Comparator<T> thenComparing(Comparator) {…};
❓Что если класс реализует 2 интерфейса с методами по умолчанию?
Для разрешения конфликта используются 2 правила:
1️⃣ Если в классе переопределён метод по умолчанию — используется метод класса.
2️⃣ В иерархии интерфейсов используется метод наследника:
interface Child extends ParentЕсли класс реализует интерфейс Child, то будет использоваться дефолтный метод интерфейса Child. В опросе перед постом ни одно правило не подходит, поэтому будет ошибка компиляции. Чтобы разрешить конфликт, класс должен явно реализовать метод get();
Endi mavjud! Telegram Tadqiqoti 2025 — yilning asosiy insaytlari 
