неоднозначен ли текст о переопределении и сокрытии методов на docs.oracle.com?

Я читаю о переопределении и сокрытии методов на веб-сайте docs.oracle.com (https://docs.oracle.com/javase/tutorial/java/IandI/override.html). Под заголовком «Статические методы» Oracle любезно резюмирует для нас:

«Различие между сокрытием статического метода и переопределением метода экземпляра имеет важные последствия:

  • Версия переопределенного метода экземпляра, которая вызывается, соответствует версии подкласса.
  • Версия скрытого статического метода, который вызывается, зависит от того, вызывается ли он из суперкласса или подкласса».

Первый пункт очень ясен. Второй пункт списка также показался мне очень информативным, но когда я перечитал его, то, похоже, запутался.

С моей точки зрения кажется, что все статические методы как в суперклассе, так и в подклассе скрыты, и при ранней привязке (привязке во время компиляции) выбирается соответствующий метод, а другой скрыт. Это выбирается ссылочным типом переменной, из которой вы ее вызываете. Однако формулировка предложения во втором пункте списка создает впечатление, что компилятор рассматривает эти два метода как один, поскольку они имеют одинаковую сигнатуру и имеют версию super и версию sub, в отличие от необходимости разделять скрытые методы и выбирать подходящий. .

мои вопросы заключаются в том, какой из этих двух углов правильный (оба метода скрыты или один метод с двумя версиями из-за сигнатуры метода), и имеет ли значение, о каком из них я думаю? бонус: мои общие мысли по этому вопросу верны?

public class Animal {
    public static void testClassMethod() {
        System.out.println("The static method in Animal");
    }
    public void testInstanceMethod() {
        System.out.println("The instance method in Animal");
    }
}

public class Cat extends Animal {
    public static void testClassMethod() {
        System.out.println("The static method in Cat");
    }
    public void testInstanceMethod() {
        System.out.println("The instance method in Cat");
    }

    public static void main(String[] args) {
        Cat myCat = new Cat();
        Animal myAnimal = myCat;
        Animal.testClassMethod();
        myAnimal.testInstanceMethod();
    }
}

//The static method in Animal
//The instance method in Cat

person Zillah    schedule 22.08.2019    source источник


Ответы (1)


С моей точки зрения кажется, что оба статических метода как в суперклассе, так и в подклассе скрыты, и при ранней привязке (привязке во время компиляции) выбирается соответствующий метод, а другой скрыт.

Ниже рассмотрим этот код:

class SuperClass {
    static void a() { System.out.println("SuperClass.a()"); }
    static void b() { System.out.println("SuperClass.b()"); }
    void testSuper() { // Call from "inside" SuperClass
        a(); // calls SuperClass.a()
        b(); // calls SuperClass.b()
    }
}
class SubClass extends SuperClass {
    static void b() { System.out.println("SubClass.b()"); }
    static void c() { System.out.println("SubClass.c()"); }
    void testSub() { // Call from "inside" SubClass
        a();   // calls SuperClass.a().
        b();   // calls SubClass.b().
        c();   // calls SubClass.c()
    }
}
class Test {
    void testSuper() { // Call SuperClass from "outside"
        SuperClass.a(); // calls SuperClass.a()
        SuperClass.b(); // calls SuperClass.b()
    }
    void testSub() { // Call SubClass from "outside"
        SubClass.a(); // calls SuperClass.a()
                      // IDE warning: The static method a() from the type SuperClass should be accessed directly
        SubClass.b(); // calls SubClass.b()
        SubClass.c(); // calls SubClass.c()
    }
}

Следует рассмотреть два случая:

  • Два метода testSuper(): вызов метода «изнутри» SuperClass или вызов метода «извне» путем уточнения с помощью SuperClass.

    В этом случае ничего не скрыто. Вы можете позвонить a() и b() в SuperClass.

    Методы в SubClass не считаются скрытыми, потому что они явно не в области видимости.

  • Два метода testSub(): вызов метода «изнутри» SubClass или вызов метода «извне» путем уточнения с помощью SubClass.

    В этом случае все 4 метода находятся в области видимости, но метод b() в SuperClass скрыт.

Как видите, только b() в SuperClass считается скрытым. b() в SubClass никогда не скрывается.

person Andreas    schedule 22.08.2019