1

我正在阅读 docs.oracle.com 网站 ( https://docs.oracle.com/javase/tutorial/java/IandI/override.html ) 上的覆盖和隐藏方法。在“静态方法”标题下,Oracle 请为我们总结一下:

“隐藏静态方法和覆盖实例方法之间的区别具有重要意义:

  • 被调用的重写实例方法的版本是子类中的版本。
  • 被调用的隐藏静态方法的版本取决于它是从超类调用还是从子类调用。”

第一个要点非常清楚。第二个要点似乎也提供了很多信息,但是当我重读它时,我似乎感到困惑。

从我的角度来看,似乎超类和子类中的每个静态方法都是隐藏的,并且通过早期绑定(编译时绑定)选择了适当的方法,而另一个是隐藏的。这是由您从中调用它的变量的引用类型选择的。然而,第二个要点中句子的表述使得编译器似乎将这两种方法视为一个,因为它们具有相同的签名,并且具有版本超级和版本子,而不是必须单独隐藏方法并选择合适的方法.

我的问题是这两个角度中的哪一个是正确的(由于方法签名,两种方法都被隐藏了,或者一种方法有两个版本),我考虑哪一个有关系吗?奖金:我对这个主题的一般想法是否正确?

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
4

1 回答 1

0

从我的角度来看,似乎超类和子类中的两个静态方法都是隐藏的,并且通过早期绑定(编译时绑定)选择了适当的方法,而另一个是隐藏的。

对于下面,请考虑以下代码:

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()方法 inSuperClass是隐藏的。

如您所见,只有b()inSuperClass被认为是隐藏的。b()里面是SubClass永远不会隐藏的。

于 2019-08-22T06:35:16.103 回答