Что такое сокрытие статического метода (method hiding) в Java?

«Что такое сокрытие статического метода (method hiding) в Java?» — вопрос из категории ООП, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Сокрытие метода (method hiding) — это механизм в Java, при котором статический метод в подклассе определяет новую реализацию для статического метода с той же сигнатурой из родительского класса. Важно: это относится только к статическим методам. Для нестатических (экземплярных) методов аналогичная ситуация называется переопределением (overriding).

Ключевое отличие от переопределения: При сокрытии используется раннее (статическое) связывание. Вызываемый метод определяется на этапе компиляции по типу ссылки, а не по типу реального объекта (как при полиморфизме и переопределении).

class Parent {
    static void print() { // Статический метод
        System.out.println("Static method in Parent");
    }
    void instancePrint() { // Метод экземпляра
        System.out.println("Instance method in Parent");
    }
}

class Child extends Parent {
    // СОКРЫТИЕ СТАТИЧЕСКОГО МЕТОДА (Method Hiding)
    static void print() {
        System.out.println("Static method in Child");
    }

    // ПЕРЕОПРЕДЕЛЕНИЕ МЕТОДА ЭКЗЕМПЛЯРА (Overriding)
    @Override
    void instancePrint() {
        System.out.println("Instance method in Child");
    }
}

public class Main {
    public static void main(String[] args) {
        Parent parentRef = new Child(); // Ссылка типа Parent на объект Child

        // Сокрытие: Выбор метода зависит от ТИПА ССЫЛКИ (Parent)
        parentRef.print(); // Вывод: "Static method in Parent"
        Parent.print();    // Вывод: "Static method in Parent"
        Child.print();     // Вывод: "Static method in Child"

        // Переопределение: Выбор метода зависит от ТИПА ОБЪЕКТА (Child)
        parentRef.instancePrint(); // Вывод: "Instance method in Child" (Полиморфизм!)
    }
}

Правила и рекомендации:

  1. Сокрытие статических методов разрешено, но часто считается плохой практикой, так как нарушает интуитивное ожидание полиморфного поведения и ведет к путанице.
  2. Для вызова скрытого родительского метода из подкласса используйте super.print(); (в нестатическом контексте) или Parent.print();.
  3. Аннотация @Override не применима к скрываемым статическим методам. Компилятор выдаст ошибку, так как это не переопределение.
  4. Лучшая практика: Избегайте сокрытия. Для статических методов используйте уникальные имена в иерархии или обращайтесь к ним явно через имя класса (ClassName.staticMethod()).