73

Javadoc说:

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

没有给我敲钟。任何显示其含义的清晰示例都将受到高度赞赏。

4

8 回答 8

175
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
于 2013-05-01T06:30:43.037 回答
56

首先方法Hiding是什么意思?

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

方法覆盖是什么意思?

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

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

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

应该如何访问静态方法?

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

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

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

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

barbarChildSuperChildChild

于 2013-05-01T06:50:37.990 回答
4

覆盖方法意味着每当在派生类的对象上调用该方法时,都会调用新的实现。

隐藏方法意味着在此类范围内(即在其任何方法的主体中,或在使用此类名称进行限定时)对该名称的非限定调用现在将调用完全不同的函数,需要限定从父类访问同名的静态方法

更多描述Java 继承:覆盖或隐藏的方法

于 2013-05-01T06:31:14.553 回答
2

如果子类定义了与超类中的类方法具有相同签名的类方法,则子类中的方法会隐藏超类中的方法。

我相信隐藏的方法在静态上下文中。静态方法本身并没有被覆盖,因为编译器本身在编译时完成了方法调用的解析。因此,如果您在基类中定义一个与父类中存在的签名相同的静态方法,那么子类中的方法会隐藏从超类继承的方法。

class Foo {
  public static void method() {
     System.out.println("in Foo");
  }
}

class Bar extends Foo {
   public static void method() {
    System.out.println("in Bar");
  }
}
于 2013-05-01T06:32:23.947 回答
1

例如,您可以覆盖超类中的实例方法,但不能覆盖静态方法。

隐藏是父类有一个名为Foo的静态方法,子类也有一个名为Foo的静态方法。

另一种情况是父类有一个名为 Cat 的静态方法,而子类有一个名为 Cat 的实例方法。(具有相同签名的静态和实例不能混合)。

public class Animal {

  public static String getCat() { return "Cat"; }

  public boolean isAnimal() { return true; }
}

public class Dog extends Animal {

  // Method hiding
  public static String getCat() { }

  // Not method hiding
  @Override
  public boolean isAnimal() { return false; }
}
于 2013-05-01T06:28:20.373 回答
0
 class P
    {
    public static  void m1()
    {
    System.out.println("Parent");
    }
}
    class C extends P
    {
    public static void m1()
    {
    System.out.println("Child");
    }
}
class Test{
    public static void main(String args[])
    {
    Parent p=new Parent();//Parent
    Child c=new Child();  //Child
    Parent p=new Child();  //Parent
    }
    }

If the both parent and child class method are static the compiler is responsible for method resolution based on reference type

class Parent
{
public void m1()
{
System.out.println("Parent");
}}
class Child extends Parent
{
public void m1()
{
System.out.println("Child")
}
}
class Test
{
public static void main(String args[])
{
Parent p=new Parent(); //Parent 
Child c=new Child();   //Child
Parent p=new Child();  //Child
}
}

If both method are not static  jvm is responsible for method resolution based on run time object
于 2019-01-10T13:23:00.120 回答
0

当超/父类和子/子类包含相同的静态方法时,包括相同的参数和签名。超类中的方法会被子类中的方法隐藏。这称为方法隐藏。

示例:1

class Demo{
   public static void staticMethod() {
      System.out.println("super class - staticMethod");
   }
}
public class Sample extends Demo {

   public static void main(String args[] ) {
      Sample.staticMethod(); // super class - staticMethod
   }
}

示例:2 - 方法隐藏

class Demo{
   public static void staticMethod() {
      System.out.println("super class - staticMethod");
   }
}
public class Sample extends Demo {
   public static void staticMethod() {
      System.out.println("sub class - staticMethod");
   }
   public static void main(String args[] ) {
      Sample.staticMethod(); // sub class - staticMethod
   }
}
于 2019-12-20T09:41:45.450 回答
0

首先,总是使用类名对静态方法进行分类。如果函数是静态的,那么它是方法隐藏,而函数是非静态的,那么方法是覆盖的。

于 2021-09-18T18:54:51.813 回答