fa
Feedback
Java: fill the gaps

Java: fill the gaps

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

Привет! Меня зовут Диана, и я занимаюсь разработкой с 2013. Здесь пишу просто и понятно про джава бэк 🔥Тот самый курс по многопочке🔥 https://fillthegaps.ru/mt Комплименты, вопросы, предложения: @utki_letyat

نمایش بیشتر

📈 تحلیل کانال تلگرام Java: fill the gaps

کانال Java: fill the gaps (@java_fillthegaps) در بخش زبانی روسی بازیگری فعال است. در حال حاضر جامعه شامل 12 549 مشترک است و جایگاه 10 121 را در دسته فناوری و برنامه‌ها و رتبه 52 862 را در منطقه روسيا دارد.

📊 شاخص‌های مخاطب و پویایی

از زمان ایجاد در невідомо، پروژه رشد سریعی داشته و 12 549 مشترک جذب کرده است.

بر اساس آخرین داده‌ها در تاریخ 07 ژوئن, 2026، کانال فعالیت پایداری دارد. در ۳۰ روز گذشته تغییر اعضا برابر -46 و در ۲۴ ساعت گذشته برابر 0 بوده و همچنان دسترسی گسترده‌ای حفظ شده است.

  • وضعیت تأیید: تأیید نشده
  • نرخ تعامل (ER): میانگین تعامل مخاطب 34.72% است و در ۲۴ ساعت نخست پس از انتشار، محتوا معمولاً N/A% واکنش نسبت به کل مشترکان کسب می‌کند.
  • دسترسی پست‌ها: هر پست به طور میانگین 0 بازدید دریافت می‌کند. در اولین روز معمولاً 0 بازدید جمع‌آوری می‌شود.
  • واکنش‌ها و تعامل: مخاطبان به‌طور فعال حمایت می‌کنند؛ میانگین واکنش به هر پست 0 است.
  • علایق موضوعی: محتوا بر موضوعات کلیدی مانند redis, hashmap, linkedhashmap, индекс, фича تمرکز دارد.

📝 توضیح و سیاست محتوایی

نویسنده این فضا را محل بیان دیدگاه‌های شخصی توصیف می‌کند:
Привет! Меня зовут Диана, и я занимаюсь разработкой с 2013. Здесь пишу просто и понятно про джава бэк 🔥Тот самый курс по многопочке🔥 https://fillthegaps.ru/mt Комплименты, вопросы, предложения: @utki_letyat

به لطف به‌روزرسانی‌های پرتکرار (آخرین داده در تاریخ 08 ژوئن, 2026)، کانال همواره به‌روز و دارای دسترسی بالاست. تحلیل‌ها نشان می‌دهد مخاطبان به‌طور فعال با محتوا تعامل دارند و آن را به نقطه اثرگذاری مهم در دسته فناوری و برنامه‌ها تبدیل کرده‌اند.

12 549
مشترکین
اطلاعاتی وجود ندارد24 ساعت
-247 روز
-4630 روز
آرشیو پست ها
Что такое идемпотентность?
Anonymous voting

Небольшой апдейт: в scala список односвязный Спасибо неравнодушным подписчикам!

Списки, часть 2: что и когда использовать В большинстве статей пишут, что LinkedList подходит для частой вставки или удаления элементов. На JavaRush также упоминают обход списка с периодической вставкой. В теории всё так, но обычно в энтерпрайзе менее изысканные задачи: 🔸 Заполнить список 🔸 Отсортировать (встроенной функцией, конечно) 🔸 Обойти все элементы 🔸 Сделать что-нибудь с помощью Stream API Для этих сценариев я сделала бенчмарки. У Stream API выделила 4 случая: ▫️ Простой однопоточный: stream→filter→collect ▫️ Сложный однопоточный: stream→map→filter→map→filter→collect ▫️ Простой с опцией parallel() ▫️ Сложный с опцией parallel() Начнём с заполнения списка. В прошлом посте выяснили, что до 100к элементов между списками почти нет разницы. ArrayList тратит много времени на копирование, а LinkedList — на создание обёрток и соединение ссылок. Если количество элементов известно заранее, его можно указать в конструкторе:
List list = new ArrayList(25);

Без лишнего копирования и переносов разница в скорости становится ошеломительной — список заполняется на 20-80% быстрее! Также ArrayList однозначно победил в номинациях: 🔹 Сортировка 🔹 Обход через цикл for 🔹 Простые Stream API 🔹 Любые Stream API с опцией parallel() В сложных однопоточных Stream API большая часть вычислений идёт на что-то полезное, и влияние оверхеда снижается. Ожидаемо:) Ещё факты против LinkedList: 🔸 Большинство классов JDK используют ArrayList для внутренних задач 🔸 Joshua Bloch (автор класса и книжки Effective Java) в 2015 написал твит:
"Does anyone actually use LinkedList? I wrote it, and I never use it."

Но аналоги LinkedList иногда встречаются. В Scala для неизменяемого списка за основу взят именно двусвязный. Возможно, это лучше для каких-то сценариев, но пока не знаю для каких. На картинке часть моих бенчмарков. N — количество элементов в списке. Зелёный цвет обозначает победителя в категории. Ярко-зелёный — разница значений более 50%. ❗️Результаты на разных железках могут отличаться ❗️

Списки, часть 1: строение и основные операции 1. Внутреннее устройство В сердце ArrayList лежит массив:
Object[] elementData;

Размер массива задаётся в конструкторе: new ArrayList(50). Значение по умолчанию — пустой массив. Структура LinkedList чуть сложнее. Каждый элемент оборачивается в класс:
private static class Node {
   E item;
   Node next;
   Node prev;
}

Т.е сам элемент списка + указатели на следующий и предыдущий элемент. В объекте LinkedList хранится ссылка на первый и последний элемент списка:
Node first;
Node last;

2. Доступ по индексу: list.get(i) или list.set(i) ArrayList просто обращается по индексу массива LinkedList идёт долгим путём. Берёт элемент first идёт по ссылкам, пока не дойдёт до i-го элемента. Затем либо возвращает значение, либо обновляет. Кажется, что второй подход гораздо дольше. И это правда🙂 Чтобы получить 5000-ый элемент в списке из 10к элементов ArrayList тратит 6 наносекунд, а LinkedList — 8750. Чем больше элементов, тем больше разница. 3. Вставка в середину списка ArrayList Допустим, для списка 🟧🟧🟧🟧 вызвали метод add(2, 🦄) Создаётся новый массив размером +1: ⬜️⬜️⬜️⬜️⬜️ Все элементы старого списка копируются туда так, чтобы образовалось свободное место для нового элемента: 🟧🟧⬜️🟧🟧 Обновляем элемент: 🟧🟧🦄🟧🟧 LinkedList Рассмотрим тот же метод add(2, 🦄): ▫️ Создаём элемент списка с двумя ссылками: ⬅️🦄➡️ ▫️ Идём до текущего элемента 2 и получаем ссылки на элементы 1 и 3 ▫️ У элемента 1 обновляем ссылку на next, у 3 — на prev Само добавление простое, но перед ним нужно пройтись по списку. Это долго, поэтому LinkedList и здесь проигрывает по скорости. 4. Заполнение списка (см код в вопросе перед постом) ArrayList ▫️ Создаётся пустой массив ▫️ При первом add размер увеличивается до 10 ▫️ При добавлении 11 элемента создаётся новый массив размером 15. Предыдущие элементы копируются, затем добавляется новый ▫️ И так далее: когда места не хватает, создаётся массив в 1.5 раза больше LinkedList У текущего tail элемента обновляется ссылка next. Новый объект записывается как tail. Что работает быстрее? Интуиция подсказывает, что LinkedList, так как для ArrayList нужно часто переносить элементы в новый массив. На самом деле операции копирования выполняются быстро, так как элементы лежат в памяти рядом, а у процессоров хорошая поддержка этой операции. Бенчмарки показывают, что до 100к элементов разницы нет, а потом побеждает ArrayList. А при миллионе элементов ArrayList копируется реже и в итоге заполняется в два раза быстрее. Внизу таблица JMH бенчмарков с моего компьютера. На других железках результаты могут отличаться. Ответ на вопрос перед постом: для 50к элементов время почти одинаковое.

Какой список в коде выше заполняется быстрее?
Anonymous voting

Какой список в коде ниже заполняется быстрее?

Списки — простая структура данных и популярная тема на собеседованиях. Просят рассказать про строение, оценить сложность операций и случаи использования. Отвечаешь, что в ArrayList быстрый доступ по индексу, а в LinkedList легко вставлять элементы в середину списка. Получаешь оффер🙂 Но это немного скучно, поэтому решила описать более жизненные кейсы и подробнее написать про строение. И самое главное — измерить время работы операций! 🔸 Часть 1: вводная. Строение списков и основные операции 🔸 Часть 2: жизненная. Что и когда использовать в коде

Сбой в работе Wildberries Сегодня необычный пост — расскажу вам новости и слухи🙂 С 14 марта в работе Wildberries наблюдались сбои — главная страница открывается, но пропали данные о прошлых заказах, новые заказы не оформляются, а в личном кабинете не отображается имя пользователя. Компания пишет о технических сбоях, но в интернете ходят слухи, что это хакерская атака. Известных деталей мало, а я не спец в кибербезопасности. Пишу свои предположения на основе слухов и похожих случаев. На самом деле может быть по-другому. Вероятный ход событий: 1️⃣ Сотрудник в Wildberries получил письмо со ссылкой, щёлкнул по ней и скачал дроппер. Дроппер — программа, которая устанавливает другое вредоносное ПО и по возможности нейтрализует защиту ОС. В Windows дропперы часто выключают службу, которая предупреждает о попытках внести изменения в систему. Письмо выглядит правдоподобно — красивая разметка, официальный стиль, актуальные новости. Это самое популярное начало атаки: 🔸 В начале пандемии COVID-19 компаниям приходили "рекомендации" по безопасной работе 🔸 Руководителю одного банка пришло письмо “журналистки РБК” с просьбой об интервью. Ссылка ведёт якобы на календарь, чтобы назначить удобное время 🔸 Во время белорусских протестов компаниям-партнёрам приходила рассылка: "Мы бастуем, поэтому к вам может прийти прокуратура с проверкой. Посмотрите по ссылке список интересующих их документов" 2️⃣ Сотрудник вышел из корпоративной сети, и дроппер скачал вредоносное ПО, который настроил удалённый доступ к компьютеру сотрудника. Но может сотрудник сделал всё сам. Плохие люди тоже встречаются. 3️⃣ В продакшн внедряются маячки из Cobalt Strike Cobalt Strike — это легальный инструмент тестирования безопасности, используется как безопасниками, так и хакерами. По статистике около 2/3 атак на крупные компании выполняется с помощью Cobalt 4️⃣ Удаляются резервные копии 5️⃣ Оставшиеся данные шифруются 6️⃣ Компании приходит письмо "Пришлите столько-то биткоинов на этот кошелёк и получите дешифратор". Иногда добавляются угрозы рассекретить информацию. Дальше всё зависит от инфраструктуры. Если у компании все бэкапы в одной подсети, и они уничтожены, то дело плохо. Всё хорошо, если остались репликации в других местах. ❓ Что с картами? Вайдберрис пишет, что эти данные защищены по стандартам PCI DSS. Но по слухам в Даркнет утекли данные 100к российских карт за последние 3 дня. Я на всякий случай перевыпустила свою карту. Надеюсь, в ближайшее время появится больше информации, и сама компания опишет ситуацию из первых рук. Тогда опыт Wildberries поможет другим компаниям🙏

Работа с задачами в Intellij iDEA Полезно для тех, кто часто переключается между задачами. 1️⃣ Для энтерпрайза В IDEA можно присоединиться к JIRA или другому таск трекеру, и у каждой задачи автоматически будет свой контекст. Контекст — это открытые вкладки и git ветка. Переключаетесь на другую задачу — автоматически открывается её набор вкладок и меняется ветка в гите. Есть интеграция с популярными таск трекерами: JIRA, Trello, Github, Bugzilla и тд Как подключить: File → Settings → Tools → Tasks → Servers → Плюсик в правом верхнем углу 2️⃣ Для личных проектов Можно сделать свой таск трекер внутри идеи: Tools → Tasks & Contexts → Open Task Дальше вводите название задачи. Их список затем доступен в правом верхнем углу. ОЧЕНЬ полезно, если вы часто переключаетесь между задачами и цените свои вкладочки🥰 У таск трекера в IDEA есть близкая фича — можно следить, сколько времени потрачено на каждую задачу: File → Settings → Tools → Tasks → Time Tracking → Enable Time Tracking IDEA показывает только полное время работы. Нельзя посмотреть статистику за день и внести её в корпоративный трекер, так что для рабочих проектов эта фича скорее бесполезна.

Основы Spring: жизненный цикл бина На тему жизненного цикла есть два доклада Жени Борисова: — Spring потрошитель (часть 1, часть 2) — Spring построитель Доклады замечательные, и документация у Spring прекрасная. Но у меня в своё время картинка не сложилась, пока я не составила простую схему. Немножко обновила её с тех времён, чтобы с вами поделиться🙂 Опишу стандартный случай — Spring Boot 5, базовые конфигурации, все бины определяются в коде и связываются через @Autowired. Основные участники: 🔸 Bean/бин/компонент — объект, которым управляет Spring 🔸 BeanDefinition — информация о будущем объекте. Имя класса, параметры конструктора и тд. 🔸 BeanFactory — отвечает за создание и хранение бинов 🔸 BeanPostProcessor (далее BPP) модифицирует бин после создания. У него два метода: — postProcessBeforeInitialization postProcessAfterInitialization 🔸 ApplicationContext — главный объект, хранит и вызывает все штучки выше Теория Что происходит и как туда внедриться: 1️⃣ Считывается информация из xml, yaml файлов Создаётся список BeanDefinition. Интерфейс — BeanDefinitionReader 2️⃣ Обработка BeanDefinition Дополняются параметры, определяется, кто от кого зависит и в каком порядке создавать бины. Интерфейс — BeanFactoryPostProcessor 3️⃣ Создаются экземпляры бинов Сначала создаются объекты @Component, потом @Bean (из классов-конфигураций). Для каждого бина порядок такой: ▫️ Вызов конструктора ▫️ Проставляются @Autowired зависимости над полями ▫️ Вызов set методов с @Autowired ▫️ Вызов методов интерфейсов *Aware ▫️ Все BPP, метод postProcessBeforeInitialization ▫️ Метод с аннотацией @PostConstruct ▫️ Метод afterPropertiesSet (если класс реализует интерфейс InitializingBean) ▫️ Метод, определенный в @Bean(initMethod = "xxx") ▫️ Все BPP, метод postProcessAfterInitialization. Тут обычно создаются прокси-классы ▫️ Бин добавляется в контейнер 4️⃣ Событие “контекст обновился” Ловится через реализацию интерфейса ApplicationListener<ContextRefreshedEvent> Или через метод с аннотацией
@EventListener
public void xxx(ContextRefreshedEvent contextRefreshedEvent) 

5️⃣ Запускается сервер 6️⃣ Событие "приложение запущено" Ловим событие ApplicationStartedEvent как в пункте 5 7️⃣ Логика в методе main, если у вас Spring Boot Менее популярные точки расширения: ▪️ Реализовать интерфейс *Aware ▪️ Поймать другие Spring Boot и Spring Core события Практика Точек расширения много, но что обычно используется: 🔸 Создать прокси-класс — BeanPostProcessor, метод after 🔸 Выполнить какую-то логику ДО старта сервера — поймать событие ContextRefreshedEvent 🔸 ПОСЛЕ старта сервера — событие ApplicationStartedEvent Часто разогрев кэша, service discovery и подобные задачи помещают в @PostConstruct, но на момент вызова не все бины могут быть готовы. При работе с событиями этой проблемы нет. И ещё пара рекомендаций: 🔹 Использовать одинаковые механизмы для одинаковых задач 🔹 Если в проекте больше трёх процессоров или задач на старте, упростите наблюдение за магией спринга. Это может быть файлик с описанием всех процессоров, очерёдностью и важными деталями. Или все процессоры поместить в одну папку. 🔹 Не помещайте бин процессоры и прослушивание событий в классы с бизнес-логикой. Нарушается принцип единственной ответственности, также могут быть проблемы с порядком обработки или количеством вызовов. ——— И небольшой апдейт по курсу: продлила скидос до 11 марта!

Смотрели доклад Spring потрошитель?
Anonymous voting

Основы Spring: что там происходит Когда я была джуниором, у меня было два этапа отношения к спрингу. Сначала "Вау, ставишь аннотацию и всё работает🥰". Но однажды аннотация не сработала. Было сложно разобраться, в чём дело, и уже через неделю я считала Spring порождением сатаны. Мне тогда не хватало общей картины, поэтому постараюсь составить её в этом посте. Spring стоит на трёх китах: 1️⃣ Dependency Injection Объекты в программе условно делятся на два вида: ▫️Компоненты — объекты, которые создаются в начале работы программы и обычно живут до конца. Контроллеры, классы сервисов, пулы соединений и т.д ▫️Данные — объекты, которые передаются между компонентами. Данные запросов, объекты пользователей, локальные переменные. Обычно живут в рамках одного запроса. Spring берёт на себя создание и связывание компонентов(или бинов). Это называется DI и упрощает жизнь разработчику. Spring — не единственный DI фреймворк. Подобные функции есть у Play framework, Dropwizard, Google Guice и т.д. Их часто используют тестировщики для автотестов. 2️⃣ Готовые компоненты Транзакции, асинхронное выполнение, ограничение доступа, работа с БД и очередями, облачные задачи. Spring предлагает готовые компоненты для большинства энтерпрайзных задач. Также Spring активно использует паттерн Декоратор (Wrapper, Proxy). От разработчика требуется минимум действий, которые хорошо описаны в мануалах. Как это выглядит. Допустим, в вашем классе есть метод doWork() с аннотацией Transactional. Spring сделает следующее: 🔸 Создаст прокси класс и переопределит метод:
public void doWork() {
   // начать транзакцию
   super.doWork(); 
   // закончить транзакцию
}

🔸 Создаст компонент с пулом транзакций и несколько промежуточных объектов. ✅ Минимум усилий от разработчика ❌ Сложно исправлять проблемы ❌ Большие накладные расходы. Spring создаёт и связывает сотни объектов на старте приложения, поэтому долго стартует и занимает много памяти 3️⃣ Кастомизация Можно написать свои аннотации или переопределить стандартное поведение. Не могу сказать, что это нужно каждый день, но раз в полгода-год появляются такие задачи. У спринга можно встроиться почти куда угодно. Это мы подробно обсудим в следующем посте. ✅ Легко встроиться в процесс ❌ Из-за этого сам процесс усложняется Именно комбо 1, 2 и 3 делает Spring таким популярным. Другие фреймворки предоставляют 1-2 пункта, но все три — только Spring. Самые популярные модули — MVC, Security, Data и Cloud. У каждого из них под капотом целый мир, и об этом тоже как-нибудь напишу.

Неделю назад я выложила анонс курса по многопоточке и получила немножко негатива на этот счёт. Я против любых убийств и любой дискриминации. Текущая ситуация — катастрофа для всех. Но в этом канале я пишу для java разработчиков и делюсь своим опытом. Если вам кажется это неуместным — отпишитесь. Курс тоже пройдёт по плану. Не вижу смысла его отменять. Ну а теперь к постам⬇️

Анонс курса по многопоточке Привет! Момент для анонса не самый удачный, но я надеюсь на лучшее🙏 Следую своему плану и стартую набор на курс по многопоточке! Кто давно ждал и уже готов → вам сюда А для тех, кто на канале недавно, расскажу подробнее. Курс строится вокруг java.util.concurrent. Изучим его в мельчайших деталях, как это перекладывается на практику и сравним разные инструменты между собой. Затронем и смежные темы: тестирование, флажки JVM, виртуальные потоки и реактивное программирование. Уроки выходят по расписанию 3 раза в неделю в предзаписи. Разберём огромное количество кейсов, лучших практик и возможных ошибок. Информации хватит для большинства многопоточных задач в энтерпрайзе. Уровень: middle/senior Старт: 21 марта Длительность: 8 недель Полная программа, отзывы(!) и запись тут: http://fillthegaps.ru/mt4 Зачем идти? ✅ Закрыть пробелы в базе. Java.util.concurrent — важная часть Java Core ✅ Работать на любых проектах. Многопоточка есть не только в хайлоад сервисах, а вообще везде. Просто обычно она прячется под слоем абстракций. ✅ Выбирать оптимальное решение для многопоточных задач, а не первое работающее со StackOverflow ✅ Круто выглядеть на собеседовании. Мало кто знает, зачем нужна модель памяти и как с ней работать на практике. Кандидат, который может это рассказать, сразу попадает в категорию "интересный"🙂 Сколько стоит? До 3 марта действует скидос: 🔸Тариф без обратной связи: 30000 23900 🔸Тариф с обратной связью: 45000 36900 Курс можно оплатить за счёт компании. Пусть ваши коллеги напишут на diana@fillthegaps.ru Если вы хотите закрыть этот пробел и разобраться с многопоточкой, и вам близок мой стиль изложения — записывайтесь, будет интересно! http://fillthegaps.ru/mt4

Настоящий сеньор Иногда в айтишных разговорах проскакивают фразы: — Я уже полгода сеньор, но чувствую себя мидлом — Вроде сеньор, но задачи делаю те же, что и раньше — Мне слишком много платят за ту ерунду, которую я делаю Это типичный синдром самозванца, и жить с ним неприятно. Что может помочь: 1️⃣ Признать текущие заслуги "Настоящий сеньор" — это как настоящий мужчина. Как будто он делает что-то особенное, чтобы стань "настоящим". Сеньором не делают заранее, должность выдают по факту. Будучи мидлом вы уже делали сеньорные задачи. Так что на текущем проекте вы точно на своём месте👍 2️⃣ Следить за общей ситуацией Даже если не хотите менять работу, полезно раз в полгода-год следить за рынком: ◾️ Обновить резюме и вписать последние достижения ◾️ Посмотреть 20 вакансий HeadHunter и наметить план развития ◾️ Походить по собеседованиям и увидеть свои пробелы. Если получится оффер, то самооценка взлетит до небес🙂 В одной компании тебя зовут в СТО, в другой даже джуниором не возьмут. Все проекты разные, и требования везде разные. Расскажу своё видение, чем отличается сеньор от мидла: Hard skills ▪️ Ориентироваться в популярных технологиях. Зачем нужны, плюсы-минусы, аналоги. Список технологий можно взять здесь. Он 2020 года, но ситуация не слишком поменялась ▪️ Настроить простой CI ▪️ Поднять систему с нуля с простой архитектурой (микросервисы, БД, очереди) ▪️ Работать с перфоманс проблемами. Знать, где посмотреть логи, что смотреть и как проверить, что проблема ушла ▪️ Целостное восприятие IT Тут сложно дать конкретный список. Просто очень странно выглядит сеньор, который не знает, что такое DNS и как масштабировать БД. Soft skills ▪️ Самостоятельность Сеньор может взять любую задачу и продвинуть её решение. Прикинуть, на каком уровне решать задачу (на фронте, в бизнес-логике, поправить конфиги, исправить ошибку в БД). Разбить на подзадачи и определить приоритеты. Сформулировать вопрос, если не хватает данных или компетенций. Предложить разные решения для разных требований ▪️ Контроль джуниоров и мидлов — провести онбординг и код-ревью, понятно отвечать на вопросы и делегировать подходящие задачи ▪️ Психологическая зрелость (не знаю как ещё назвать) — принимать решения в условиях неопределённости, признавать свою неправоту и незнание. Не заметать проблемы под ковёр и понимать приоритеты. Уважительно и продуктивно общаться. Понимать, когда устал/раздражён, и не принимать серьёзных решений в этом состоянии. Спокойно удалять свой код, если он не нужен. Но ещё раз — чётких стандартов нет. Каждый, кто уже стал сеньором, заслужил этот грейд, проделал большой путь и хорошо делал свою работу🔥

Интерфейсы, часть 3: разница с абстрактным классом Отличия интерфейса и абстрактного класса — супер популярный вопрос на собеседовании. Во времена java 7 ответ был простой: "В интерфейсе нет реализаций". Сейчас мир стал сложнее, и в интерфейсе есть приватные, статические и дефолтные методы с готовой реализацией. Это сближает интерфейсы с абстрактными классами. ❓В чём теперь разница интерфейса и абстрактного класса? 🛠 Функциональность В абстрактный класс можно добавить многое: ▪️Конструктор ▪️Реализация экземплярных методов ▪️Нестатические поля ▪️private static поля ▪️Модификаторы final, synchronized, protected Интерфейс сильно ограничен: ▪️Только статические поля ▪️Методам с реализацией недоступны экземплярные поля, поэтому их возможности слабее ✍🏻 Синтаксис Абстрактный класс: ▫️ Ключевое слово extends ▫️ В имени часто содержится Abstract, Template, Base ▫️ Класс реализует не больше одного абстрактного класса Интерфейс: ▫️ Ключевое слово implements ▫️ Класс может реализовать несколько интерфейсов ▫️ 5 лет назад интерфейсам было модно добавлять суффикс able: Iterable, Comparable. Норма сегодняшнего дня — называть интерфейс по тем же правилам, что и класс. 💫 Назначение Абстрактный класс — шаблон класса. Вспомогательная структура, чтобы не дублировать код в классах одной иерархии. Интерфейс описывает методы для верхнеуровнего взаимодействия с классом, модулем или системой. ⭐️ Репутация Абстрактный класс сокращает объем необходимого кода, когда иерархия классов конечна или известна заранее. Большое количество абстрактных классов считается анти-паттерном, у такой системы плохая читаемость, и в неё сложно вносить изменения. Интерфейс используется в большинстве паттернов GoF и принципах SOLID. Поддерживает инкапсуляцию.

Интерфейсы, часть 2: методы по умолчанию Когда готовила материал по дефолтным методам, то перечитала почти все переписки разработчиков этой фичи. Огромное удовольствие — следить за спором опытных людей с высокой инженерной культурой и мощными теоретическими знаниями. Профессионализм завораживает🥰 Но я расскажу вам итог. В java 8 появилась новая возможность — методы с заданной реализацией:
interface Adapter {
   default int get() {…}
}

Класс, который реализует интерфейс, переопределяет такой метод при необходимости. ❓Зачем? 1️⃣ Облегчить изменения API Во времена java 7 в интерфейсах были только определения методов:
interface Collection<Т> {
   void add(Т);
   Т get();
}

Чтобы добавить, удалить или поменять сигнатуру метода нужно одновременно поменять код и в интерфейсе, и во всех реализациях. Если всё в рамках одного проекта, то проблем нет. Но если мы пишем библиотеку, то задача усложняется. Пользователи могут столкнутся с проблемами совместимости при переходе на новую версию. Задача дефолтных методов — сгладить этот процесс, предоставить приемлемую или временную альтернативу. В JDK основная цель дефолтных методов — поддержка Stream API в коллекциях. 2️⃣ Вспомогательные методы Которые не входят в прямую функциональность интерфейса, но их удобно добавить сюда, а не в каждый класс реализации. Нарушается принцип Interface segregation и часто похоже на костыль. Не одобряю, но такое встречается🙂 3️⃣ Комбинации базовых методов Мы обсуждали это в прошлом посте. В интерфейсе есть методы, которые по сути — комбинация других методов этого же интерфейса. Для таких комбинаций можно сделать статический метод. Он вызываются через имя интерфейса и недоступен у экземпляров. Если это неудобно, метод можно сделать как метод по умолчанию. Пример: интерфейс Comparator Цепочка из 2 компараторов — это 2 вызова compare и объединение результатов. Логика всегда одинакова, и нет смысла дублировать её в каждом подклассе:
default Comparator thenComparing(Comparator) {…};

❓Что если класс реализует 2 интерфейса с методами по умолчанию? Правила такие: 🔸 Если в классе переопределён метод по умолчанию — используется метод класса 🔸 Если один интерфейс наследуется от другого — используется метод наследника 🔸 В остальных случаях — ошибка компиляции Отсюда ответы на вопросы перед постом: 1️⃣ Ошибка компиляции 2️⃣ Напечатается В

Вопрос 2. Что выведется в консоль? (интерфейс В теперь расширяет интерфейс А)
Anonymous voting

Вопрос 2. Что выведется в консоль? (интерфейс В теперь расширяет интерфейс А)

Вопрос 1. Что выведется на консоль?
Anonymous voting