Java中隐藏的方法是什么?即使是JavaDoc的解释也令人困惑

2022-08-31 13:25:21

Javadoc 说:

被调用的隐藏方法的版本是超类中的版本,被调用的被覆盖方法的版本是子类中的版本。

不会给我敲响警钟。任何表明其含义的清晰示例都将受到高度赞赏。


答案 1
public class Animal {
    public static void foo() {
        System.out.println("Animal");
    }
}

public class Cat extends Animal {
    public static void foo() {  // hides Animal.foo()
        System.out.println("Cat");
    }
}

在这里,据说是隐藏的。隐藏不像重写那样起作用,因为静态方法不是多态的。因此,将发生以下情况:Cat.foo()Animal.foo()

Animal.foo(); // prints Animal
Cat.foo(); // prints Cat

Animal a = new Animal();
Animal b = new Cat();
Cat c = new Cat();
Animal d = null;

a.foo(); // should not be done. Prints Animal because the declared type of a is Animal
b.foo(); // should not be done. Prints Animal because the declared type of b is Animal
c.foo(); // should not be done. Prints Cat because the declared type of c is Cat
d.foo(); // should not be done. Prints Animal because the declared type of d is Animal

在实例而不是类上调用静态方法是一种非常糟糕的做法,永远不应该这样做。

将其与实例方法进行比较,实例方法是多态的,因此被覆盖。调用的方法取决于对象的具体运行时类型:

public class Animal {
    public void foo() {
        System.out.println("Animal");
    }
}

public class Cat extends Animal {
    public void foo() { // overrides Animal.foo()
        System.out.println("Cat");
    }
}

然后会发生以下情况:

Animal a = new Animal();
Animal b = new Cat();
Cat c = new Cat();
Animal d = null;

a.foo(); // prints Animal
b.foo(); // prints Cat
c.foo(); // prints Cat
d.foo(): // throws NullPointerException

答案 2

首先,方法隐藏是什么意思?

方法隐藏意味着子类定义了与超中的类方法具有相同签名的类方法。在这种情况下,超类的方法被子类隐藏。它表示:执行的方法的版本不会由用于调用它的对象确定。实际上,它将由用于调用该方法的引用变量的类型确定。

方法覆盖是什么意思?

方法重写意味着子类定义了与超类中的实例方法具有相同签名和返回类型(包括协变类型)的实例方法。在这种情况下,超类的方法被子类覆盖(替换)。它表示:执行的方法的版本将由用于调用它的对象确定它不会由用于调用该方法的引用变量的类型确定

为什么不能重写静态方法?

因为,静态方法是根据调用它们的类静态解析的(即在编译时),而不是动态的,因为实例方法是根据对象的运行时类型多态解析的。

应如何访问静态方法?

应以静态方式访问静态方法。即通过类本身的名称而不是使用实例。

以下是方法覆盖和隐藏的简短演示:

class Super
{
  public static void foo(){System.out.println("I am foo in Super");}
  public void bar(){System.out.println("I am bar in Super");}
}
class Child extends Super
{
  public static void foo(){System.out.println("I am foo in Child");}//Hiding
  public void bar(){System.out.println("I am bar in Child");}//Overriding
  public static void main(String[] args)
  {
     Super sup = new Child();//Child object is reference by the variable of type Super
     Child child = new Child();//Child object is referenced by the variable of type Child
     sup.foo();//It will call the method of Super.
     child.foo();//It will call the method of Child.

     sup.bar();//It will call the method of Child.
     child.bar();//It will call the method of Child again.
  }
}

输出为

I am foo in Super
I am foo in Child
I am bar in Child
I am bar in Child

显然,如前所述,因为 是类方法,因此调用的版本将由引用 的对象的引用变量的类型(即 Super 或 Child)确定。如果它被变量引用,则调用 of。如果它被变量引用,则调用 of。
然而
Since 是实例方法,因此调用的版本完全由用于调用它的对象(即 )确定。无论通过哪个引用变量(或)调用它,要调用的方法总是的。foofooChildSuperfooSuperChildfooChildbarbarChildSuperChildChild