覆盖与隐藏Java - 困惑

Los*_*kpr 77 java methods inheritance overriding

我对Overriding与隐藏Java有何不同感到困惑.任何人都可以提供有关这些差异的更多细节吗 我阅读了Java Tutorial,但示例代码仍让我感到困惑.

为了更清楚,我理解压倒一切.我的问题是我没有看到隐藏是有什么不同的,除了一个是在实例级别而另一个在类级别.

查看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.");
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我们有一个子类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();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后他们说:

该程序的输出如下:

Animal中的类方法.

Cat中的实例方法

对我来说,直接从Animal类调用类方法testClassMethod(),在Animal类中执行该方法这一事实非常明显,没有什么特别之处.然后他们从对myCat的引用调用testInstanceMethod(),所以再次非常明显的是,然后执行的方法是Cat实例中的方法.

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

Cat.testClassMethod();
Run Code Online (Sandbox Code Playgroud)

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

这告诉我,在子类中编写一个静态方法,与父级中的签名相同,几乎可以覆盖.

希望我清楚地表明我的困惑,有人可以解决问题.首先十分感谢!

Kaz*_*ara 98

超越基本上支持后期绑定.因此,将在运行时决定调用哪个方法.它用于非静态方法.隐藏适用于所有其他成员(静态方法,实例成员,静态成员).它基于早期绑定.更清楚的是,在编译期间决定要调用或使用的方法或成员.

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

在第二次调用中myAnimal.testInstanceMethod(),它调用非静态方法.这就是你所说的运行时多态.直到运行时才调用哪种方法.

有关进一步说明,请阅读此内容.

  • 谢谢您的快速解答,这可以澄清它!我注意到在JavaRanch示例中,他们使用变量来调用类方法,而不是直接使用类,这使它更易于理解。我猜在Java教程中,他们直接使用了该类,因为使用实例调用静态方法可能不是一个好习惯,但是他们应该使用_myAnimal.testClassMethod()_而不是_Animal.testClassMethod()_。 (3认同)

Why*_*ugo 18

静态方法是隐藏的,非静态方法被覆盖.当调用不符合"something()"vs"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();
    }

}
Run Code Online (Sandbox Code Playgroud)

OUTPUT:

animal.something
dog.eat
Run Code Online (Sandbox Code Playgroud)


Rud*_*udy 13

这是覆盖和隐藏之间的区别,

  1. 如果父类和子类中的两个方法都是实例方法,则它会调用覆盖.
  2. 如果父类和子类中的两个方法都是静态方法,则称为隐藏.
  3. 一种方法在父级中不是静态的,而在子级中是一种实例.反之亦然.

在此输入图像描述

  • 你直接从教程中剪切并粘贴了那张桌子,OP说这并不能帮助他理解. (2认同)