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 }

  程序运行结果:

          

  在上面的例子中,由于子类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 }

  程序运行结果:

        

  在上面的例子中,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 }

  程序运行结果:

         

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

java多态的实现机制的更多相关文章

  1. Java多态的实现机制是什么,写得非常好!

    作者:crane_practice www.cnblogs.com/crane-practice/p/3671074.html Java多态的实现机制是父类或接口定义的引用变量可以指向子类或实现类的实 ...

  2. Java 多态的实现机制

    http://my.oschina.net/onlytwo/blog/52222 是父类或接口定义的引用变量可以指向子类或实现类的实例对象,而程序调用的方法在运行期才动态绑定,就是引用变量所指向的具体 ...

  3. Java多态实现的机制

    Java提供了编译时多态和运行时多态两种多态机制.前者是通过方法重载实现的,后者是通过方法的覆盖实现的. 在方法覆盖中,子类可以覆盖父类的方法,因此同类的方法会在父类与子类中有着不同的表现形式. 在J ...

  4. 深入理解Java多态机制

    从字节码层面来看,Java中的所有方法调用,最终无外乎转换为如下几条调用指令. invokestatic: 调用静态方法. invokespecial: 调用实例构造器<init>方法,私 ...

  5. java的动态代理机制详解

    在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的 ...

  6. C++和java多态的区别

    C++和java多态的区别 分类: Java2015-06-04 21:38 2人阅读 评论(0) 收藏 举报  转载自:http://www.cnblogs.com/plmnko/archive ...

  7. 深入浅出Java并发包—锁机制(一)

    前面我们看到了Lock和synchronized都能正常的保证数据的一致性(上文例子中执行的结果都是20000000),也看到了Lock的优势,那究竟他们是什么原理来保障的呢?今天我们就来探讨下Jav ...

  8. Java的动态代理机制详解(转)

    在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的 ...

  9. Java 多态的实现原理

    一个对象变量可以指示多种实际类型的现象称为多态 允许不同类的对象对同一消息做出响应.方法的重载.类的覆盖正体现了多态. 1.多态的机制 1.1 本质上多态分两种 .编译时多态(又称静态多态) .运行时 ...

随机推荐

  1. github命令大全

    github是一种开源的版本控制工具,现在已经得到很多人的应用.所以想介绍一下github的一些使用. github安装 github提供了桌面客户端,我们也可以通过命令行的方式来进行控制. wind ...

  2. ApacheHttpServer修改httpd.conf配置文件

    转自:https://blog.csdn.net/dream1120757048/article/details/77427351 1. 安装完 Apache HTTP Server 之后,还需要修改 ...

  3. navicat连接Oracle数据库提示错误 ORA-12514

    这个是服务名写错了,服务名的字段在Oracle安装路径里找 这个我的服务名,这好像是重装Oracle就会变我之前的事orcl,重装之后发现连接不上数据库了,就倔强着找到了它 备注:如果是连接远程Ora ...

  4. pwd - 显示出当前/活动目录的名称

    总览 (SYNOPSIS) pwd [OPTION] 描述 (DESCRIPTION) 显示出 完整的 当前 活动目录 名称. --help 显示 帮助 信息, 然后 退出 --version 显示 ...

  5. vue,一路走来(12)--父与子之间传参

    今天想起一直没有记录父组件与子组件的传参问题,这在项目中一直用到. 父向子组件传参 Index.vue父组件中 <component-a :msgfromfa="(positionno ...

  6. MySQL01---简介及安装

    目录 MySQL简介及安装 DBA工作内容 DBA的职业素养 MySQL简介及安装 01 什么是数据? 02 什么是数据库管理系统 03 数据库管理系统种类 关系型数据库(RDMS)与非关系型数据库( ...

  7. JVM分为哪些区,每一个区干嘛的?

    程序计数器PC 线程私有的 它可以看做是当前线程所执行的字节码的行号指示器 内存区域中唯一一个没有规定任何OutOfMemoryError的区域 Java虚拟机栈 线程私有的 每个方法在执行的同时都会 ...

  8. SpringBoot中jar包转war包

    参考博客 https://blog.csdn.net/qq_33689414/article/details/81812761 https://blog.csdn.net/u013412772/art ...

  9. Sass Maps的函数-map-remove($map,$key)、keywords($args)

    map-remove($map,$key) map-remove($map,$key) 函数是用来删除当前 $map 中的某一个 $key,从而得到一个新的 map.其返回的值还是一个 map.他并不 ...

  10. Java反射初识

    反射Class类 Class类是反射的根源,很多很多的类,经过抽象,得出了一个Class类,包括类名,构造方法,属性方法等.得到Class类的对象的三种方式: Object类中的getClass()方 ...