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 之类的话来访问父类方法,对吗?那么这里发生了什么隐藏。它只是重申一个事实,即调用的函数是与引用变量相关联的函数,而不是与实例相关联的函数。仍然无法弄清楚对这个术语的具体需求 没有。 superthis 一样,不能在静态上下文中使用。不过,您可以从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 变量引用,则调用Superfoo。如果它被 Child 变量引用,则调用 Childfoo, 由于bar 是实例方法,因此调用的bar 的版本完全由用于调用它的对象(即Child)确定。无论通过哪个引用变量(SuperChild)调用它,要调用的方法总是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注释的快捷键是啥哦

Java中的“内部地址”是啥?

Xtext:使用@annotations 创建“JavaDoc”注释

BitSet 的 size() 方法的原因是啥?

Java 新手 - 一般 JavaDoc 问题