Java: fill the gaps
Привет! Меня зовут Диана, и я занимаюсь разработкой с 2013. Здесь пишу просто и понятно про джава бэк 🔥Тот самый курс по многопочке🔥 https://fillthegaps.ru/mt Комплименты, вопросы, предложения: @utki_letyat
إظهار المزيد📈 نظرة تحليلية على قناة تيليجرام Java: fill the gaps
تُعد قناة Java: fill the gaps (@java_fillthegaps) في القطاع اللغوي الروسية لاعباً نشطاً. يضم المجتمع حالياً 12 548 مشتركاً، محتلاً المرتبة 10 113 في فئة التكنولوجيات والتطبيقات والمرتبة 52 819 في منطقة روسيا.
📊 مؤشرات الجمهور والحراك
منذ تأسيسه في невідомо، حقق المشروع نمواً سريعاً وجمع 12 548 مشتركاً.
بحسب آخر البيانات بتاريخ 08 يونيو, 2026، تحافظ القناة على نشاط مستقر. خلال آخر 30 يوماً تغيّر عدد الأعضاء بمقدار -43، وفي آخر 24 ساعة بمقدار -3، مع بقاء الوصول العام مرتفعاً.
- حالة التحقق: غير موثّقة
- معدل التفاعل (ER): يبلغ متوسط تفاعل الجمهور 34.73%. وخلال أول 24 ساعة من النشر يحصد المحتوى عادةً N/A% من ردود الفعل نسبةً إلى إجمالي المشتركين.
- وصول المنشورات: يحصل كل منشور على متوسط 0 مشاهدة. وخلال اليوم الأول يجمع عادةً 0 مشاهدة.
- التفاعلات والاستجابة: يتفاعل الجمهور بانتظام؛ متوسط التفاعلات لكل منشور يبلغ 0.
- الاهتمامات الموضوعية: يركز المحتوى على مواضيع رئيسية مثل redis, hashmap, linkedhashmap, индекс, фича.
📝 الوصف وسياسة المحتوى
يصف المؤلف القناة بأنها مساحة للتعبير عن الآراء الذاتية:
“Привет! Меня зовут Диана, и я занимаюсь разработкой с 2013. Здесь пишу просто и понятно про джава бэк
🔥Тот самый курс по многопочке🔥
https://fillthegaps.ru/mt
Комплименты, вопросы, предложения: @utki_letyat”
بفضل وتيرة التحديث المرتفعة (أحدث البيانات بتاريخ 09 يونيو, 2026) تحافظ القناة على حداثتها ومستوى وصول مرتفع. وتُظهر التحليلات تفاعلاً نشطاً من الجمهور، ما يجعلها نقطة تأثير مهمة ضمن فئة التكنولوجيات والتطبيقات.
interface Интерфейс {
public void метод();
}
Классы реализуют эти методы под угрозой ошибки компиляции:
class M implements Интерфейс {
public void метод() {…};
}
Java 8
Появились 2 новых возможности:
1️⃣ Метод по умолчанию с заданной реализацией:
default void метод() {…};
Конкретный класс переопределяет его при необходимости.
❓Зачем они нужны?
Дефолтные методы уместны в трёх случаях, об этом будет статья в среду.
2️⃣ Статические методы с реализацией:
static void метод() {…};
Статические методы не наследуются и не переопределяются. Вызвать такой метод можно только через имя интерфейса:
Интерфейс.метод()❓Зачем они нужны? В интерфейсе определяется необходимый минимум методов. Например, в Collection это методы add(), remove() и другие. Чем меньше методов, тем больше свободы действий у конкретных классов. Эти базовые методы комбинируются между собой в другие полезные методы: ▪️Поиск элемента, ▪️Поиск минимального элемента, ▪️Скопировать коллекцию, Каждый из этих методов - всего лишь комбинация базовых, которая не зависит от конкретного класса. Чтобы не копировать код в каждый класс, сделайте такой метод статическим методом в интерфейсе:
static E min() {…};
До java 8 статические методы объединяли в утилитный класс с похожим именем. Например, методы binarySearch, copy, min реализованы в классе Collections.
Java 9
Можно добавить private и private static методы с реализацией:
private void m() {…};
private static void m() {…};
Эти методы недоступны для классов, реализующих интерфейс.
❓Зачем они нужны?
Чтобы выделить под-методы в дефолтных и статических методах, таким образом улучшить читаемость и избежать дублирования кода.
С методами разобрались, а какие поля можно добавлять в интерфейс?
Только константы с модификаторами public static. Из-за того, что других вариантов нет, в Intellij IDEA модификаторы public и static подсвечиваются как избыточные и вместо
public static int NUM = 1;допустима запись:
int NUM = 1;Такие поля компилируются в статические! Правильный ответ на вопрос: Ошибку компиляции в последней версии java вызовут варианты:
default int get(); private int get(); public static int get();У приватных, статических и дефолт методов в интерфейсах должна быть реализация.
String.join("-","1","2");
// 1-2
Можно использовать со списком строк:
List<String> list = ...;
String.join("-", list);
🔸Убрать пробелы и служебные символы
▪️с начала строки:
str.stripLeading();
▪️в конце строки:
str.stripTrailing();
▪️с обеих сторон:
str.strip();
В классе уже присутствует метод trim(), который тоже стирает неподходящие символы. strip() корректнее определяет недопустимые символы, в том числе экзотические виды пробелов ('\u00A0', '\u2007', '\u202F').
🔸Проверить, что строка пуста:
str.isBlank()На замену StringUtils.isBlank() из библиотеки Apache Commons. 🔸Создать стрим из строки. Можно разделить текст ▪️по линиям:
str.lines()
▪️по символам: str.chars()
🔸Продублировать строку:
"<td>".repeat(3);
// <td><td><td>String str;Ассоциированный объект имеет тот же тип или производный. Т.к типы известны заранее, проверка аргументов происходит во время компиляции. ✅ Отлавливается много ошибок. ✅ Быстро работает в рантайме. ✅ Предсказуемое поведение. ✅ Легко тестировать. При динамической типизации указатель не имеет типа. Во время работы программы в переменную можно записать любые значения:
value = "а" value = 4Аргументы проверяются во время вызова метода. Такие программы в разы короче и легко адаптируются к изменениям. Java является языком со статической типизацией. Второй вопрос, на который отвечает система типов: что делать, если метод принимает тип А, но приходит объект типа Б? Можно: ▪️Бросить ошибку. ▪️Преобразовать Б в тип А. У языка сильная типизация, если допустимо мало преобразований. Если много, то типизация слабая. Речь идёт о неявных преобразованиях, которые делает компилятор или исполняющая среда. Пример:
5L + 1
Язык Ruby не разрешает складывать числа разных типов, а java приведёт единицу к типу long и выполнит сложение. Выражение
5 + trueв java вызовет ошибку компиляции. JavaScript спокойно переведёт true в единицу. Компилятор java может перевести: - подкласс в суперкласс - long в int и наоборот - int в Integer и наоборот и так далее. Некоторые правила работают в одних условиях, некоторые в других. В целом java считается языком с сильной типизацией. Вернёмся к вопросу перед постом. Метод
id ожидает аргумент типа Long, а передаётся примитивный int. В правилах преобразований нет перехода int → Long, поэтому будет ошибка компиляции. Достичь цели можно в 2 шага:
int → long
long → Long
Компилятор может выполнить только один шаг, второе преобразование делает программист. Поэтому подходящий ответ:
(long) intValuefilter(...).findFirst().isPresent()
а можно короче, понятнее и быстрее:
noneMatch(...)
Иногда стримы даже не нужны, много полезных методов есть в интерфейсе Collections. Например, максимальный элемент в списке быстрее найти через Collections.max(...), чем с использованием стрима.
Больше примеров
4️⃣ Объединить однотипные операции.
Чаще это касается сложной фильтрации:
filter(1).filter(2).filter(3)
можно ускорить в 2-4 раза, если объединить условия:
filter(1 & 2 & 3)try-catch-finally в спецификации описывается через 24 предложения "если". Логика запутанная, и легко допустить ошибку.
Чтобы решать такие задачки, воспользуйтесь следующей моделью:
Результатом блока try-catch-finally могут быть 3 варианта:
🔸Ничего
🔸Возврат значения
🔸Исключение
Представим, что результат записывается в переменную result. В начале работы там "ничего".
Блоки обрабатываются в строгом порядке:
1️⃣ try
2️⃣ catch
3️⃣ finally
На каждом шаге переменная result может быть перезаписана. Итоговое значение result и будет результатом выполнения. Особый случай — при вызове System.exit(0) выполнение прекращается сразу же .
Разберём пример из опроса:
▫️try установит результат на "вернуть try".
▫️Блока catch нет.
▫️В finally результат меняется на "вернуть finally".
Итог: вернётся "finally"
Другой пример:
try { throw new NPE(); }
catch (SecurityEx e)
{ return "ex"; }
finally {}
▫️В блоке try результатом станет "NPE".
▫️Блок catch пропускается, т.к нет подходящего типа исключения.
▫️В блоке finally результат не переопределяется.
Итог: выброс NPE.
Этот пример важен, потому что такие ошибки часто встречаются на практике. Блок finally - не оберег от исключений. Если результат "исключение" дальше не переопределён, он пробрасывается в вышестоящий метод.String info(Request req) {
return req.toString(); }
Для нормальной работы параметр req не должен быть пустым. Мы можем:
1️⃣ Оставить как есть: тогда JVM выбросит NullPointerException(NPE)
2️⃣ Добавить проверку и самим бросить исключение:
if (req==null) throw new NPE();3️⃣ Добавить проверку и вернуть null:
if (req==null) return null;4️⃣ Добавить проверку и вернуть Optional.empty():
if (req==null) return Optional.empty();Оценим их с точки зрения производительности и дизайна. Начнём с производительности. Запустим каждый вариант миллион раз: ▪️14 мс - JVM исключение ▪️2 мс - явный выброс исключения ▪️0,03 мс - null ▪️0,03 мс - Optional.empty() Что это значит? 1️⃣ Создание исключения гораздо дольше, чем выход из метода. Время уходит на создание стек-трейса - чем он глубже, тем хуже производительность. Стек-трейс из сервиса на Spring Boot собирается в 50-100 раз дольше, чем стек-трейс из метода main. 2️⃣ Если исключение явно создаётся в коде, JVM переиспользует ранее собранный стэк-трейс. Так получается выигрыш в 5-10 раз, но разница с вариантом без исключения всё ещё внушительна. По этим цифрам легко решить, что исключения - удар по производительности. 10 лет назад была тенденция избегать исключений любой ценой. Например, возвращать из метода пару (результат, код_ошибки). В 2020 это уже не актуально. Если взаимодействие в системе не построено на исключениях, то это капля в море относительно других операций. В примере сверху исключение создаётся миллион раз подряд - такого в продакшене обычно нет. Исключения делают код чище: 🔹Понятное возвращаемое значение 🔹В части throws явно обозначены непредвиденные ситуации 🔹Логика метода и обработка ошибок разделены Теперь сравним создание исключения и возврат null с точки зрения дизайна. Исключение подразумевает обработку ошибки, например: 🔸Показать пользователю сообщение. 🔸Прекратить работу с файлом. 🔸Поменять формат данных. Optional.empty(), null или объект по умолчанию возвращается, когда реагировать на ситуацию необязательно. Например, когда данные быстро устаревают. Возвращаемый тип Optional удобнее использовать: не нужно смотреть в документации, возвращает ли функция пустой результат, и как он обозначается: null, -1 или 0.
static, private, final. Метод определяется по типу ссылки во время компиляции, и его нельзя переопределить. Благодаря раннему связыванию JVM не тратит ресурсы во время работы программы, поэтому скорость вызова этих методов чуть выше.
Позднее связывание работает для остальных public и protected методов. JVM в рантайме определяет тип объекта и метод, который нужно вызвать. Этот механизм лежит в основе полиморфизма, наследования и инкапсуляции.
Статические методы в классах Parent и Child не переопределяют друг друга и относятся к разным классам. Над методом в классе Child нельзя даже поставить @Override и вызвать внутри super.getName();
Поэтому правильный ответ в опросе выше — "Parent", потому что метод определён во время компиляции по типу указателя.
Если посмотреть на вызов метода у объекта, то непонятно, статический он или обычный, учитывается тип экземпляра или нет. Это приводит к ошибкам и считается плохой практикой. Настолько плохой, что для объекта Intellij IDEA даже не показывает статические методы в выпадающем списке. Хороший вариант — вызывать статические методы, обращаясь к классу:
println(Parent.getName());На собеседованиях встречается модификация этого вопроса — один метод
getName() статический, а другой — нет. В этом случае будет ошибка компиляции, потому что непонятно, какой механизм связывания использовать.
متاح الآن! بحث تيليغرام 2025 — أهم رؤى العام 
