Javadoc说:
被调用的隐藏方法的版本是超类中的版本,被调用的重写方法的版本是子类中的版本。
不会向我敲钟。任何清楚的例子都可以看出其含义。
Answers:
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();
Animal c = new Cat();
Animal d = null;
a.foo(); // prints Animal
b.foo(); // prints Cat
c.foo(); // prints Cat
d.foo(): // throws NullPointerException
super
一样this
,不能在静态环境中使用。你可以调用Animal.foo()
从Cat.foo()
,虽然,但两种方法有共同之处其实没什么,除了他们的姓名和签名。隐藏用于区别于覆盖。但是方法隐藏并不是真正有用的,而方法覆盖是OO设计的关键部分之一。
首先,方法隐藏是什么意思?
方法隐藏意味着子类定义了一个类方法,该类方法具有与超类中的类方法相同的签名。在那种情况下,超类的方法被子类隐藏。它表示:执行的方法的版本将不会由用于调用该方法的对象来确定。实际上,它将由用于调用该方法的引用变量的类型确定。
方法覆盖是什么意思?
方法覆盖意味着子类定义了一个实例方法,该方法具有与超类中的实例方法相同的签名和返回类型(包括协变类型)。在这种情况下,超类的方法被子类覆盖(替换)。它表示:执行的方法的版本将由用于调用它的对象确定。它不会由用于调用该方法的引用变量的类型确定。
为什么不能覆盖静态方法?
因为,静态方法是根据类被静态地(即在编译时)解析的,而不是像实例方法那样动态地解析的,实例方法是根据对象的运行时类型进行多态解析的。
应该如何访问静态方法?
静态方法应以静态方式访问。即通过类本身的名称而不是使用实例。
这是有关方法重写和隐藏的简短演示:
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
是class方法,所以foo
被调用的版本将由引用的对象的引用变量(即Super或Child)的类型确定Child
。如果被Super
变量引用foo
,Super
则调用of 。如果它被Child
变量引用foo
,Child
则调用of 。
鉴于,
因为bar
是实例方法,所以bar
被调用的版本仅由Child
用于调用它的对象(即)确定。不管通过哪个参考变量(Super
或Child
)进行调用,将要调用的方法始终为Child
。
到覆盖的方法的装置,每当该方法被称为派生类的物体上时,新的实现将被调用。
到隐藏的方法的装置,在这个类的(即,在其任何方法,或当合格与这个类的名称的团体)的范围,以该名称的不合格呼叫现在将调用完全不同的功能,需要鉴定从父类访问同名的静态方法。
更多说明Java继承:覆盖或隐藏的方法
如果子类定义的类方法具有与超类中的类方法相同的签名,则该子类中的方法会将其隐藏在超类中。
我相信隐藏的方法是在静态上下文中。静态方法本身并不会被覆盖,因为编译器在编译时本身就对方法调用进行了解析。因此,如果您在基类中定义了一个与父类中存在的方法相同的签名的静态方法,则子类中的方法将隐藏从超类继承的方法。
class Foo {
public static void method() {
System.out.println("in Foo");
}
}
class Bar extends Foo {
public static void method() {
System.out.println("in Bar");
}
}
例如,您可以覆盖超类中的实例方法,但不能覆盖静态方法。
隐藏是父类的静态方法名为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; }
}
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
当父/父类和子/子类包含相同的静态方法(包括相同的参数和签名)时。父类中的方法将隐藏超类中的方法。这称为方法隐藏。
范例: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
}
}