java中多态的实现机制

多态的概念:

  简单来说就是事物在运行过程中存在的不同状态,即父类或接口定义的引用变量指向子类或具体实现类的实例对象。程序调用方法在运行期才进行动态绑定,而不是引用变量的类型中定义的方法。

多态存在的前提:

1、存在继承关系,子类继承父类;

2、子类重写父类的方法;

3、父类引用指向子类对象。

具体实例:

1、定义一个父类:Animal

 1 package demo;
 2
 3  class Animal{
 4          int num = 10;
 5      static int age = 20;
 6          public void eat() {
 7          System.out.println("动物吃饭");
 8      }
 9          public static void sleep() {
10          System.out.println("动物睡觉");
11      }
12          public void run() {
13          System.out.println("动物奔跑");
14      }
15  } 

2、子类:Cat继承Animal

 1 package demo;
 2
 3 public class Cat extends Animal{
 4     int num=80;
 5     static int age=90;
 6     String name="TomCat";
 7     @Override
 8     public void eat() {
 9         // TODO Auto-generated method stub
10         System.out.println("猫吃饭");
11     }
12     public static void sleep(){
13         System.out.println("猫在睡觉");
14     }
15     public void catchMouse() {
16         // TODO Auto-generated method stub
17         System.out.println("猫抓老鼠");
18     }
19 }

3、测试类:Test1

 1 package demo;
 2
 3 public class Test1 {
 4
 5     public static void main(String[] args) {
 6         Animal am=new Cat();
 7         am.eat();
 8         am.sleep();
 9         am.run();
10         System.out.println(am.num);
11         System.out.println(am.age);
12         //以下两行注释内容稍后解释
13         //am.catchMouse();
14         //System.out.println(am.name);
15     }
16
17 }

以上三段代码充分体现了多态存在的前提条件:

1、存在继承关系:Cat 类继承了Animal类;

2、子类要重写父类方法:子类Cat重写(override)了父类Animal的两个方法eat(),sleep(),其中eat()为普通方法,sleep()为静态方法(static);

3、父类引用指向子类对象:测试类中Animal am=new Cat();,语句在堆内开辟了一块内存分配给子类(Cat),并把栈内存中的父类(Animal)的引用指向了这个Cat对象。

测试类运行后的结果:

可以看出:

  1、子类Cat重写的父类Animal的普通方法eat()的输出结果为“猫吃饭”;

     2、子类Cat重写的父类Animal的静态方法sleep()的输出结果为“动物睡觉”;

  3、未被子类Cat重写的父类Animal的普通方法run()的输出结果为“动物奔跑”;

  4、子类Cat继承的父类Animal属性,输出结果分别为父类属性;

  5、输出子类Cat特有属性和方法则会报错。

因此,根据以上分析可以总结出多态成员访问的特点:

Animal am=new Cat();

成员变量:

编译看左(父类),运行看左(父类);

成员方法:

编译看左(父类),运行看右(子类),输入动态绑定;

静态方法:

编译看左(父类),运行看左(父类),静态方法被提升到类级别,算不上重写,所以访问还是看父类;

多态以后不能使用子类特有的属性和方法,在子类Cat中有一个特有的属性String name="TomCat";并且还有一个特有的抓老鼠的方法catchMouse()。但是在测试类Test1中,尝试调用子类的特有方法和打印子类特有的属性时,就会报错。

  那么如果想要使用子类特有的属性和方法该怎么办呢?可以把这个父类引用指向的子类对象强制转换为子类Cat类型,这样am就是子类Cat类型的引用,指向的也是Cat对象了,这样就能够使用子类的一些属性和方法了。

 1 package demo;
 2
 3 public class Test1 {
 4
 5     public static void main(String[] args) {
 6         Animal am=new Cat();
 7         am.eat();
 8         am.sleep();
 9         am.run();
10         System.out.println(am.num);
11         System.out.println(am.age);
12         //以下两行注释内容稍后解释
13         //am.catchMouse();
14         //System.out.println(am.name);
15         System.out.println("-------------------------");
16         Cat ct=(Cat)am;
17         ct.eat();
18         ct.sleep();
19         ct.run();
20         ct.catchMouse();
21         System.out.println(ct.num);
22         System.out.println(ct.age);
23         System.out.println(ct.name);
24     }
25
26 }

  执行强转语句Cat ct=(Cat)am;后,ct就指向了最开始在堆内存中创建的那个Cat对象了。这就是多态的功能,使用起来十分的灵活,觉少了多余对象的创建,不用为了使用子类的某个方法再去堆内存中开辟一块新的空间给一个新的子类对象了。

花木兰替父从军的例子:

  大家都知道花木兰替父从军的例子,花木兰替父亲花弧从军。那么这时候花木兰是子类,花弧是父类。花弧有自己的成员属性年龄,姓名,性别。花木兰也有这些属性,但是很明显二者的属性值完全不一样。花弧有自己的非静态成员方法‘骑马杀敌’,同样花木兰也遗传了父亲一样的方法‘骑马杀敌’。花弧还有一个静态方法‘自我介绍’,每个人都可以问花弧姓甚名谁。同时花木兰还有一个自己特有的非静态成员方法‘涂脂抹粉’。但是,现在花木兰替父从军,女扮男装。这时候相当于父类的引用(花弧这个名字)指向了子类对象(花木兰这个人),那么在其他类(其他的人)中访问子类对象(花木兰这个人)的成员属性(姓名,年龄,性别)时,其实看到的都是花木兰她父亲的名字(花弧)、年龄(60岁)、性别(男)。当访问子类对象(花木兰这个人)的非静态成员方法(骑马打仗)时,其实都是看到花木兰自己运用十八般武艺在骑马打仗。当访问花木兰的静态方法时(自我介绍),花木兰都是用她父亲的名字信息在向别人作自我介绍。并且这时候花木兰不能使用自己特有的成员方法‘涂脂抹粉’。-----多态中的向上转型

  那么终于一将功成万骨枯,打仗旗开得胜了,花木兰告别了战争生活。有一天,遇到了自己心爱的男人,这时候爱情的力量将父类对象的引用(花弧这个名字)强制转换为子类对象本来的引用(花木兰这个名字),那么花木兰又从新成为了她自己,这时候她完全是她自己了。名字是花木兰,年龄是28,性别是女,打仗依然那样生猛女汉子,自我介绍则堂堂正正地告诉别人我叫花木兰。终于可以使用自己特有的成员方法‘涂脂抹粉’了。从此,花木兰完全回到了替父从军前的那个花木兰了。-----多态中的向下转型

  向上转型向下转型一定是在多态这个前提下,同时向上转型是安全的,向下转型则不安全。比如强制将女儿变成父亲,则女儿可以使用父亲的身份存在,反之,将父亲变成女儿,就变成东方不败了,系统此时就会报错非法类型转换。另外开发中一般利用多态声明形式参数,并将创建子类的匿名对象作为实际参数。

原文地址:https://www.cnblogs.com/wwkcherry/p/9532509.html

时间: 2024-10-31 05:10:44

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

深入Java核心 Java中多态的实现机制(1)

多态性是Java面向对象的一个重要机制,本文将向您详细介绍Java语言中多态性的实现原理和方法,通过多态一点带出更多Java面向对象有趣而实用的知识. 多态性是面向对象程序设计代码重用的一个重要机制,我们曾不只一次的提到Java多态性.在Java运行时多态性:继承和接口的实现一文中,我们曾详细介绍了Java实现运行时多态性的动态方法调度:今天我们再次深入Java核心,一起学习Java中多态性的实现. “polymorphism(多态)”一词来自希腊语,意为“多种形式”.多数Java程序员把多态看

Java中的内存处理机制和final、static、final static总结

Java中的内存处理机制和final.static.final static总结 装载自:http://blog.csdn.net/wqthaha/article/details/20923579 Java程序运行在JVM上,可以把JVM理解成Java程序和操作系统之间的桥梁,JVM实现了Java的平台无关性,由此可见JVM的重要性.所以在学习Java内存分配原理的时候一定要牢记这一切都是在JVM中进行的,JVM是内存分配原理的基础与前提.         一个完整的Java程序运行过程会涉及以

Java中多态的一些简单理解

什么是多态 1.面向对象的三大特性:封装.继承.多态.从一定角度来看,封装和继承几乎都是为多态而准备的.这是我们最后一个概念,也是最重要的知识点. 2.多态的定义:指允许不同类的对象对同一消息做出响应.即同一消息可以根据发送对象的不同而采用多种不同的行为方式.(发送消息就是函数调用) 3.实现多态的技术称为:动态绑定(dynamic binding),是指在执行期间判断所引用对象的实际类型,根据其实际的类型调用其相应的方法. 4.多态的作用:消除类型之间的耦合关系. 5.现实中,关于多态的例子不

个人对Java中多态的一些简单理解

什么是多态 面向对象的三大特性:封装.继承.多态.从一定角度来看,封装和继承几乎都是为多态而准备的.这是我们最后一个概念,也是最重要的知识点. 多态的定义:指允许不同类的对象对同一消息做出响应.即同一消息可以根据发送对象的不同而采用多种不同的行为方式.(发送消息就是函数调用) 实现多态的技术称为:动态绑定(dynamic binding),是指在执行期间判断所引用对象的实际类型,根据其实际的类型调用其相应的方法. 多态的作用:消除类型之间的耦合关系. 现实中,关于多态的例子不胜枚举. 下面是多态

Java中的内存分配机制

Java的内存分为两种:一种是栈内存,一种是堆内存. 在函数中定义的一些基本类型变量和对象的引用都在函数的栈内存中分配.当在一个代码块中定义一个变量的时候,java就在栈中为其分配内存,当超过作用域的时候内存自动释放. 对内存用来存放new创建的对象和数组.在堆中分配的内存,由java虚拟机的垃圾回收机器管理.java的堆是运行时数据区,堆的优势是可以动态的分配内存大小,生存周期也不必事先告诉编译器,但是,由于是动态分配,存取速度慢. 栈的优势是比堆的存取速度快,仅次于寄存器,栈数据可以共享,但

从虚拟机指令执行的角度分析JAVA中多态的实现原理

从虚拟机指令执行的角度分析JAVA中多态的实现原理 前几天突然被一个"家伙"问了几个问题,其中一个是:JAVA中的多态的实现原理是什么? 我一想,这肯定不是从语法的角度来阐释多态吧,隐隐约约地记得是与Class文件格式中的方法表有关,但是不知道虚拟机在执行的时候,是如何选择正确的方法来执行的了.so,趁着周末,把压箱底的<深入理解Java虚拟机>拿出来,重新看了下第6.7.8章中的内容,梳理一下:从我们用开发工具(Intellij 或者Eclipse)写的 .java 源程

Java 中的等待唤醒机制透彻讲解

线程的状态 首先了解一下什么是线程的状态,线程状态就是当线程被创建(new),并且启动(start)后,它不是一启动就进入了执行状态(run),也不是一直都处于执行状态. 这里说一下Java 的Thread类里面有一个State方法,这个方法里面涵盖了6种线程的状态,如下: public enum State { // 尚未启动的线程的线程状态. NEW, // 可运行线程的线程状态. RUNNABLE, // 线程的线程状态被阻塞,等待监视器锁定. BLOCKED, // 等待线程的线程状态.

java中存在垃圾回收机制,但是还会有内存泄漏的问题,原因是

答案是肯定的,但不能拿这一句回答面试官的问题.分析:JAVA是支持垃圾回收机制的,在这样的一个背景下,内存泄露又被称为"无意识的对象保持".如果一个对象引用被无意识地保留下来,那么垃圾回收器不仅不会处理这个对象,而且也不处理被这个对象引用的其它对象."内存泄露"就是内存中某些内存不可被回收. 举个例子:如果对一个栈(Stack类)先是进行入栈操作,之后再进行出栈操作,那么弹出来的对象将不会被当做垃圾回收,即使使用栈的客户程序不再引用这些对象,因为栈内部存在着对这些已

Java中的垃圾回收机制&amp;内存管理

1. Java在创建对象时,会自动分配内存,并当该对象引用不存在的时候,释放这块内存. 为什么呢? 因为Java中使用被称为垃圾收集器的技术来监视Java程序的运行,当对象不再使用时,就自动释放对象所使用的内存. 垃圾收集器是自动运行的,无须显式地请求垃圾收集器,程序运行时,垃圾收集器会不时检查对象的各个引用,并回收无引用对象所占用的内存. 可以调用System类中的静态gc()方法来运行垃圾收集器. 2. Java语言并不要求JVM有gc,也没有规定gc如何工作. Java垃圾回收机制是为所有