Что произойдёт при попытке вызвать статический метод интерфейса через тип реализующего класса?
Такая попытка завершится ошибкой компиляции: статические методы интерфейса не наследуются реализующими классами. Их вызывают через имя самого интерфейса, а не через тип класса, который этот интерфейс реализует.
Статические методы появились в интерфейсах в Java 8 вместе с механизмом default-методов. Это позволило добавлять к интерфейсам вспомогательные операции и развивать библиотечные API без размещения всех связанных функций в отдельных утилитных классах.
При этом статические методы интерфейса намеренно не стали частью полиморфного контракта: они относятся к самому интерфейсу как к пространству имён, а не к экземплярам его реализаций.
Разработчик может ошибочно ожидать, что статический метод интерфейса доступен через любой реализующий класс так же, как унаследованный статический метод класса. В результате код не скомпилируется, даже если класс явно реализует интерфейс.
Это важно при проектировании API: вызов через класс создаёт ложное впечатление, что метод является частью возможностей конкретной реализации. Кроме того, статический метод интерфейса нельзя переопределить или вызвать полиморфно через ссылку на интерфейс.
Статический метод интерфейса принадлежит декларации интерфейса. Реализующий класс не получает его в набор унаследованных членов, поэтому обращение к методу через имя класса недопустимо.
Вызов TextRules.isBlank(...) разрешается по имени интерфейса. Вызов DefaultRules.isBlank(...) не разрешается, потому что метод не наследуется классом.
Такой метод не участвует в переопределении, динамическом диспетчеризации и выборе реализации по фактическому типу объекта. Интерфейс может иметь статический метод с тем же именем, что и статический метод класса-реализации, но это будут независимые методы, а не отношение переопределения.
Статический метод интерфейса также не наследуется дочерними интерфейсами. Если несколько интерфейсов объявляют одноимённые статические методы, конфликта default-методов нет: каждый метод вызывается через имя своего интерфейса.
Практический компромисс такой: интерфейсный статический метод удобен для операции, тесно связанной с конкретным контрактом интерфейса. Для общей утилиты, не относящейся к контракту, обычно понятнее использовать отдельный final-класс с закрытым конструктором.
В библиотеке есть интерфейс TextRules, описывающий правила обработки текста. Команда разместила в нём статический метод проверки пустого значения, а затем попыталась вызывать его через DefaultRules, считая этот класс полноценным владельцем API. Сборка упала после замены одного класса реализации на другой.
Рассматривались два варианта. Первый — оставить метод в интерфейсе и явно вызывать его через TextRules: это сохраняет связь операции с контрактом, но требует дисциплины в именовании вызовов. Второй — перенести метод в отдельный класс TextUtils: такой вариант лучше подходит для независимой утилиты, но отделяет её от интерфейса.
Выбрали вызов через TextRules, поскольку проверка была частью правил самого контракта, а не особенностью конкретной реализации. После исправления вызовов смена реализации интерфейса перестала влиять на доступ к вспомогательной операции, а код явно показывает владельца метода.
Нет. Статический метод не вызывается через объектную ссылку, даже если её объявленный тип совпадает с интерфейсом. Корректный способ — обращение через имя интерфейса; это подчёркивает отсутствие связи с конкретным экземпляром.
Нет, потому что статический метод интерфейса не наследуется классом и не входит в механизм переопределения. Класс может объявить одноимённый статический метод, но он будет самостоятельным методом класса, а не реализацией метода интерфейса.
Методы останутся независимыми: статические методы интерфейсов не наследуются дочерними интерфейсами и не переопределяются. Вызов через имя родительского интерфейса обращается к родительскому методу, а через имя дочернего — к методу дочернего интерфейса, если он там объявлен.