zoukankan      html  css  js  c++  java
  • java多态的实现机制

    Java提供了编译时多态和运行时多态两种多态机制。前者是通过方法重载实现的,后者是通过方法的覆盖实现的。

      在方法覆盖中,子类可以覆盖父类的方法,因此同类的方法会在父类与子类中有着不同的表现形式。

         在Java语言中,基类的引用变量不仅可以指向基类的实例对象,也可以指向其子类中的实例对象。同样,接口中的引用变量也可以指向其实现类的实例对象。而程序调用的方法在运行时期才动态绑定(绑定是指将一个方法调用和一个方法主体联系在一起),绑定的是引用变量所指向的具体实例对象的方法,也就是内存中正在运行的那个对象的方法,而不是引用变量的类型中定义的方法。通过这种动态绑定实现了多态。由于只有在运行时才能确定调用哪个方法,因此通过方法覆盖实现的多态也可以被称为运行时多态。

      

      示例一:

     1 public class Base {
    2     public Base(){
    3         g();
    4     }
    5
    6     public void g() {
    7         System.out.println("Base g()");
    8     }
    9    
    10     public void f() {
    11         System.out.println("Base f()");
    12     }
    13 }
     1 public class Derived extends Base{
    2    
    3     public void g() {
    4         System.out.println("Derived g()");
    5     }
    6    
    7     public void f() {
    8         System.out.println("Derived f()");
    9     }
    10    
    11     public static void main(String[] args) {
    12         Base base=new Derived();
    13         base.f();
    14         base.g();
    15     }
    16 }

      程序运行结果:

              img

      在上面的例子中,由于子类Derived的f()方法和g()方法与父类Base方法同名,因此Derived的方法会覆盖Base的方法。在执行 Base base=new Derived(); 语句时,会调用Base类的构造函数,而在Base的构造函数中,执行了g()方法,由于Java语言的多态性,此时会调用子类Derived的g()方法,而不是父类Base 的g()方法,因此会输出"Derived g()".由于实际创建的是Derived对象,后面的方法调用都会调用子类Derived的方法。

     

      但要注意,若此时父类中没有f()方法和g()方法,会编译报错。

     

      示例二:

     1 package Test;
    2
    3 public class Base {
    4     private String baseName="base";
    5     public Base(){
    6         callName();
    7     }
    8    
    9     public void callName(){
    10         System.out.println(baseName);
    11     }
    12    
    13     static class Sub extends Base{
    14         private String baseName="sub";
    15         public void callName(){
    16             System.out.println(baseName);
    17         }
    18     }
    19    
    20     public static void main(String[] args) {
    21         Base base=new Sub();
    22     }
    23 }

      程序运行结果:

            img

      在上面的例子中,new Sub();在创造派生类的过程中首先创建基类对象,然后才能创建派生类。创建基类即默认调用Base()方法,在方法中调用callName()方法,由于派生类中存在此方法,则被调用的callName()方法是派生类中的方法,此时派生类中普通成员变量(private String baseName="sub";)还未构造,所以变量baseName的值为null。

     

     

      此外,只有类的方法才有多态的概念,类的成员变量没有多态的概念。示例如下:

    1 public class Base {
    2     public int i=1;
    3 }
    1 public class Derived extends Base{
    2    
    3     private int i=2;
    4    
    5     public static void main(String[] args) {
    6         Base base=new Derived();
    7         System.out.println(base.i);
    8     }
    9 }

      程序运行结果:

             img

      由此可见,成员变量是无法实现多态的,类的成员变量的值取父类还是子类并不取决于创建对象的类型,而是取决于所定义变量的类型,这是在编译期间确定

  • 相关阅读:
    聊聊 print 的前世今生
    在树莓派里搭建 Lighttpd 服务器
    如何重复执行一条命令直至运行成功?
    手把手教你Windows Linux双系统的安装与卸载
    你以为只有马云会灌鸡汤?Linux 命令行也会!
    Linux 下三种提高工作效率的文件处理技巧
    太高效了!玩了这么久的Linux,居然不知道这7个终端快捷键!
    Linux下分析bin文件的10种方法
    Linux下几个与磁盘空间和文件尺寸相关的命令
    如何让你的脚本可以在任意地方都可执行?
  • 原文地址:https://www.cnblogs.com/dmzna/p/11830652.html
Copyright © 2011-2022 走看看