隐藏在Java中的方法是什么?甚至JavaDoc的解释也令人困惑

JAT*_*MON 61 java oop method-hiding

Javadoc说:

被调用的隐藏方法的版本是超类中的版本,被调用的重写方法的版本是子类中的版本.

不响铃给我.任何显示其含义的明确例子都将受到高度赞赏.

JB *_*zet 132

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

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
Run Code Online (Sandbox Code Playgroud)

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

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

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

然后会发生以下情况:

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

a.foo(); // prints Animal
b.foo(); // prints Cat
c.foo(); // prints Cat
d.foo(): // throws NullPointerException
Run Code Online (Sandbox Code Playgroud)

  • 非常好的答案,你是唯一一个提到在实例上调用静态方法是邪恶的人.+1 (25认同)
  • 不,`super`,就像`this`一样,不能在静态环境中使用.你可以从`Cat.foo()`调用`Animal.foo()`,但这两种方法实际上没有任何共同点,除了它们的名称和签名.隐藏用于区分重写.但是方法隐藏并不是真正有用,而方法覆盖是OO设计的关键部分之一. (8认同)
  • 我怀疑你仍然可以通过说 super.foo 之类的东西来访问父类方法,对吗?那么这里发生了什么隐藏。它只是重申这样一个事实,即被调用的函数是与引用变量相关的函数,而不是与实例相关的函数。仍然无法弄清楚对这个术语的具体需求 (3认同)
  • 从语言上来说,我希望可以说 Animal 的静态方法隐藏了 Cat 的静态方法。因此,我花了一段时间才理解这个概念。如果选择事物 A 是因为另一个事物 B 被事物 A 遮挡,那么我们通常会说 B 被 A 隐藏,不是吗? (2认同)

Vis*_*l K 39

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

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

方法覆盖是什么意思?

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

为什么不能覆盖静态方法?

因为静态方法是基于调用它们的类而静态地(即在编译时)解析的,而不是动态解析,例如在基于对象的运行时类型以多态方式解析的实例方法的情况下.

如何访问静态方法?

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

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

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

输出是

I am foo in Super
I am foo in Child
I am bar in Child
I am bar in Child
Run Code Online (Sandbox Code Playgroud)

显然,如指定的那样,因为foo是类方法所以foo调用的版本将由引用该对象的引用变量(即Super或Child)的类型决定Child.如果它被引用Super变量则fooSuper被调用.如果它被引用Child变量则fooChild被调用.
然而,
由于bar是实例方法,因此bar调用的版本仅由Child用于调用它的对象(即)确定.无论通过哪个引用变量(SuperChild)调用它,将要调用的方法始终是Child.