📜  可以重写Java中的私有方法吗

📅  最后修改于: 2020-03-23 00:51:54             🧑  作者: Mango

让我们首先考虑以下Java程序作为重写或运行时多态的简单示例。

class Base {
  public void fun() {
     System.out.println("父类 fun");
  }
}
class Derived extends Base {
  public void fun() {  // 重写父类的fun()
     System.out.println("派生类 fun");
  }
  public static void main(String[] args) {
      Base obj = new Derived();
      obj.fun();
  }
}

程序输出“派生类 fun”。
基类引用’obj’引用派生类对象(请参见表达式“ Base obj = new Derived()”)。在obj上调用fun()时,将根据引用对象的类型而不是引用进行调用。

使私有方法可以重写吗?
预测以下程序的输出。

class Base {
  private void fun() {
     System.out.println("父类 fun");
  }
}
class Derived extends Base {
  private void fun() {
     System.out.println("派生类 fun");
  }
  public static void main(String[] args) {
      Base obj = new Derived();
      obj.fun();
  }
}

我们收到编译器错误“ fun()在Base中具有私有访问权限”。因此,编译器尝试调用基类函数,而不是派生类,这意味着fun()不会被重写。

内部类可以访问其外部类的私有成员。如果我们扩展内部类并在内部类中创建fun()怎么办?
一个内部类可以访问其外部类的私有成员,例如,在下面的程序中,内部类展示访问私有数据成员。

/* Java展示通过内部类重写外部private方法 */
class Outer {
     private String msg = "芒果文档";
     private void fun() {
          System.out.println("外部 fun()");
     }
     class Inner extends Outer {
         private void fun()  {
               System.out.println("外部私有成员: " + msg);
         }
     }
     public static void main(String args[])  {
          // 分别创建外部对象和内部对象
          Outer o = new Outer();
          Inner  i   = o.new Inner();
          // 这将调用内部的fun
          i.fun();
          // o.fun() 调用外部的fun(无运行时多态)
          o = i;
          o.fun();
     }
}

输出:

外部私有成员: 芒果文档
外部 fun()

在上面的程序中,我们创建了一个外部类和一​​个内部类。我们从Outer扩展了Inner,并在Outer和Inner中都创建了一个fun()方法。如果我们观察到输出,则很明显,方法fun()未被重写。之所以如此,是因为私有方法是在编译时绑定的,并且引用变量的类型(而不是它所引用的对象的类型)决定了要调用的方法。附带说明一下,由于静态绑定,私有方法在性能上可能会更好(与非私有和非最终方法相比)。

与C++的比较
1)在Java中,允许内部类访问外部类的私有数据成员。此行为和C++相同
2)在Java中,永远不能重写声明为private的方法,它们在编译期间实际上是有界的。此行为与C++不同。在C++中,我们可以有虚拟私有方法