覆盖与隐藏 Java - 困惑

我对覆盖与隐藏在Java中的区别感到困惑。任何人都可以提供更多关于它们如何不同的细节吗?我阅读了Java教程,但示例代码仍然让我感到困惑。

更清楚的是,我对覆盖的理解很好。我的问题是,我不认为隐藏有什么不同,除了一个在实例级别,而另一个在类级别。

看看 Java 教程代码:

public class Animal {
    public static void testClassMethod() {
        System.out.println("Class" + " method in Animal.");
    }
    public void testInstanceMethod() {
        System.out.println("Instance " + " method in Animal.");
    }
}

然后我们有一个子类:Cat

public class Cat extends Animal {
    public static void testClassMethod() {
        System.out.println("The class 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();
    }
}

然后他们说:

此程序的输出如下所示:

动物中的类方法。

Cat 中的实例方法。

对我来说,直接从类调用类方法在类中执行方法的事实是非常明显的,没有什么特别的。然后他们调用 from a reference to ,所以再次非常明显,然后执行的方法就是 实例中的方法。testClassMethod()AnimalAnimaltestInstanceMethod()myCatCat

从我所看到的,呼叫隐藏的行为就像覆盖一样,那么为什么要进行这种区分呢?如果我使用上面的类运行此代码:

Cat.testClassMethod();

我会得到:Cat中的类方法。但是,如果我从 Cat 中删除 ,那么我会得到:Animal 中的 class 方法。testClassMethod()

这让我知道,在子类中编写一个静态方法,其签名与父级中的签名相同,几乎可以完成重写。

希望我能够弄清楚我感到困惑的地方,有人可以透露一些线索。提前非常感谢!


答案 1

覆盖基本上支持后期绑定。因此,在运行时决定将调用哪个方法。它适用于非静态方法。

隐藏适用于所有其他成员(静态方法、实例成员、静态成员)。它基于早期的绑定。更清楚的是,要调用或使用的方法或成员是在编译时决定的。

在您的示例中,第一个调用是对方法的调用,因此可以非常确定要调用哪个方法。Animal.testClassMethod()static

在第二次调用 中,调用非静态方法。这就是您所说的运行时多态性。直到运行时才决定要调用哪个方法。myAnimal.testInstanceMethod()

有关进一步说明,请阅读覆盖与隐藏


答案 2

静态方法是隐藏的,非静态方法被重写。当调用不是限定的“something()”与“this.something()”时,差异是显着的。

我似乎真的不能把它放在文字上,所以这里有一个例子:

public class Animal {

    public static void something() {
        System.out.println("animal.something");
    }

    public void eat() {
        System.out.println("animal.eat");
    }

    public Animal() {
        // This will always call Animal.something(), since it can't be overriden, because it is static.
        something();
        // This will call the eat() defined in overriding classes.
        eat();
    }

}


public class Dog extends Animal {

    public static void something() {
        // This method merely hides Animal.something(), making it uncallable, but does not override it, or alter calls to it in any way.
        System.out.println("dog.something");
    }

    public void eat() {
        // This method overrides eat(), and will affect calls to eat()
        System.out.println("dog.eat");
    }

    public Dog() {
        super();
    }

    public static void main(String[] args) {
        new Dog();
    }

}

输出:

animal.something
dog.eat

推荐