Java中隐藏的方法是啥?甚至 JavaDoc 的解释也令人困惑
Posted
技术标签:
【中文标题】Java中隐藏的方法是啥?甚至 JavaDoc 的解释也令人困惑【英文标题】:What is method hiding in Java? Even the JavaDoc explanation is confusingJava中隐藏的方法是什么?甚至 JavaDoc 的解释也令人困惑 【发布时间】:2013-04-25 04:26:58 【问题描述】: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
【讨论】:
非常好的答案,你是唯一一个提到在实例上调用静态方法是邪恶的。 +1 我怀疑你仍然可以通过说 super.foo 之类的话来访问父类方法,对吗?那么这里发生了什么隐藏。它只是重申一个事实,即调用的函数是与引用变量相关联的函数,而不是与实例相关联的函数。仍然无法弄清楚对这个术语的具体需求 没有。super
和 this
一样,不能在静态上下文中使用。不过,您可以从Cat.foo()
调用Animal.foo()
,但这两种方法实际上没有任何共同之处,除了它们的名称和签名。隐藏用于区分覆盖。但是方法隐藏并不是真正有用,而方法覆盖是 OO 设计的关键部分之一。
从语言上讲,我希望可以说 Animal 的静态方法隐藏了 Cat 的静态方法。因此,我花了一些时间来理解这个概念。如果选择 A 是因为 B 被 A 遮挡了,那么我们通常会说 B 被 A 隐藏了,不是吗?
请你详细说明你的这个实现如何显示方法隐藏?【参考方案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
显然,正如指定的那样,由于foo
是类方法,所以调用的foo
的版本将由引用Child
对象的引用变量的类型(即Super 或Child)确定。如果它被Super
变量引用,则调用Super
的foo
。如果它被 Child
变量引用,则调用 Child
的 foo
。而,
由于bar
是实例方法,因此调用的bar
的版本完全由用于调用它的对象(即Child
)确定。无论通过哪个引用变量(Super
或Child
)调用它,要调用的方法总是Child
。
【讨论】:
【参考方案3】:覆盖一个方法意味着每当在派生类的对象上调用该方法时,都会调用新的实现。
隐藏一个方法意味着在这个类的范围内(即在它的任何方法的主体中,或者当使用这个类的名称进行限定时)对该名称的非限定调用将现在调用一个完全不同的函数,需要一个资格才能从父类访问同名的静态方法。
更多描述Java Inheritance: Overwritten or hidden methods
【讨论】:
【参考方案4】:如果子类定义的类方法与超类中的类方法具有相同的签名,则子类中的方法会隐藏超类中的方法。
我相信隐藏方法是在静态上下文中。静态方法本身并没有被覆盖,因为编译器本身在编译时完成了方法调用的解析。因此,如果您在基类中定义了一个与父类中存在的签名相同的静态方法,那么子类中的方法会隐藏从超类继承的方法。
class Foo
public static void method()
System.out.println("in Foo");
class Bar extends Foo
public static void method()
System.out.println("in Bar");
【讨论】:
【参考方案5】:例如,您可以覆盖超类中的实例方法,但不能覆盖静态方法。
隐藏是父类有一个名为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;
【讨论】:
【参考方案6】: 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
【讨论】:
【参考方案7】:当父类/父类和子/子类包含相同的静态方法时,包括相同的参数和签名。超类中的方法会被子类中的方法隐藏。这称为方法隐藏。
示例: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
【讨论】:
【参考方案8】:首先总是使用类名对静态方法进行分类。 如果函数是静态的,那么它是方法隐藏,而函数是非静态的,那么方法是覆盖的。
【讨论】:
您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center。以上是关于Java中隐藏的方法是啥?甚至 JavaDoc 的解释也令人困惑的主要内容,如果未能解决你的问题,请参考以下文章
ASCII 艺术文档的流行 JavaDoc 实践是啥? [关闭]
androidstudio添加javadoc注释的快捷键是啥哦