什么是多态

  多态是一个对象的多种实现,是建立在继承的基础上的,即对象“人”,有老师和学生不同的实现,其实总结起来就是允许将子类类型的指针赋值给父类类型的指针。

多态的发生条件

  多态发生的前提是:1. 要有继承发生; 2. 要有方法的重写; 3. 要有父类引用指向子类对象。

多态中成员的访问特点

  一个类中有成员变量,构造方法,成员方法和静态方法,那在多态中这些成员的访问特点是如何的呢,下面通过代码来总结下。

/**
* Created by lili on 15/10/21.
*/ class Person {
String name = "person name"; public Person() {
System.out.println("person construct");
} public void show() {
System.out.println("person show!");
} public static void play() {
System.out.println("person play");
}
} class Student extends Person {
String name = "Student name";
String nickName = "young boy"; public Student() {
System.out.println("student construct");
} public void show() {
System.out.println("student show!");
} public static void play() {
System.out.println("student play");
} public void study() {
System.out.println("student study");
}
} public class PolymorphismTest {
public static void main(String[] args) {
Person person = new Student(); System.out.println("***********************************");
System.out.println(person.name); System.out.println("***********************************");
person.show(); System.out.println("***********************************");
person.play(); // System.out.println("***********************************");
// person.study(); //编译报错,找不到符号 // System.out.println(person.nickName);//编译报错,找不到符号 }
}

运行结果如下:

person construct
student construct
***********************************
person name
***********************************
student show!
***********************************
person play Process finished with exit code 0

对结果进行解释和总结  

  1. 成员变量
    编译看左边,运行看左边。

    如果在父类引用总访问子类特有的成员变量则编译报错,例如System.out.println(person.nickName);//编译报错,找不到符号

    子类和父类都有的,即子类继承的,不管对子类的成员变量如何做变化,最后显示的该成员变量的结果都是对父类成员变量操作后的结果。
  2. 构造方法
    这个是继承中的知识,是分层次初始化的,调用默认构造初始化,即虽然是new的Student,但是是先初始化Person,再初始化Student,所以打印顺序是:

    person construct
    student construct

  3. 成员方法    

    编译看左边,运行看右边。

    编译的时候只能调用父类有的成员方法,调用子类特有的成员方法则报错,这是多态的弊端,不能通过分类引用调用子类非继承成员方法。但是可以向下转型实            现这个功能,下文讲述。

    运行的时候,由于成员方法重写了,所以运行子类中的该方法的具体实现,这点很有意思!所以person.show()最后打印结果是student show;
  4. 静态方法
    编译看左边,运行看左边。
    静态和类相关,算不上重写,所以,访问还是左边的

多态的好处

  多态的好处在于简化了代码,提供了很好的可扩充性。例如有一个“形状”对象,目前有“圆形”,“长方形”,“正方形”三种实现,在画图的测试方法中,方法的传递参数可以是“形状”类型,你传进来的可以是“圆形”,“长方形”,“正方形”对象,最后调用“形状”来画图,执行的是不同对象的画图方法。如果没有多态,则每个对象都需要专门写一个测试方法来测试,而现在只需要一个了。

如何访问多态中子类特有成员方法和成员变量:多态中的向下转型和向上转型

  对于子类中的非继承自父类的特有方法和成员变量,例如student中的play方法,肯定有用的,但是如何调用呢?在这里就需要用到向下转型,把父类的引用利用强制类型转换给子类,然后通过这个子类引用去调用。示例程序如下:

/**
* Created by lili on 15/10/21.
*/ class Person {
String name = "person name"; public Person() {
System.out.println("person construct");
} public void show() {
System.out.println("person show!");
} public static void play() {
System.out.println("person play");
}
} class Student extends Person {
String name = "Student name";
String nickName = "young boy"; public Student() {
super.name = "student modified name";
System.out.println("student construct");
} public void show() {
System.out.println("student show!");
} public static void play() {
System.out.println("student play");
} public void study() {
System.out.println("student study");
}
} class Teacher extends Person{ } public class PolymorphismTest {
public static void main(String[] args) {
Person person = new Student(); Student student = (Student)person;
student.study(); Teacher teacher = (Teacher)person;
teacher.show(); // System.out.println(person.nickName);//编译报错,找不到符号 }
}

运行结果:

person construct
student construct
student study
Exception in thread "main" java.lang.ClassCastException: Student cannot be cast to Teacher
at PolymorphismTest.main(PolymorphismTest.java:54)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140) Process finished with exit code 1

  向下转型的特点

     1. 需要用到强制类型转换,将父类强制转型为子类,但是父类指向的对象必须是该子类实例化对象。

     2. 向下转型为父类引用指向子类对象相同的引用,可以实现子类特有方法和成员变量的访问。

  向上转型的特点

    1. 发生在传参或者new子类对象给父类引用的过程中

多态一个有趣的例子

/**
* Created by lili on 15/10/21.
*/ class Person { public void show() {
play();
} public void play() {
System.out.println("person play");
}
} class Student extends Person { public void play() {
System.out.println("student play");
}
} class Monitor extends Student{
public void show() {
super.show();
}
public void play() {
System.out.println("Monitor play");
}
} public class PolymorphismTest {
public static void main(String[] args) {
Person person = new Student();
person.show();//student中没有重写show,所以调用的是person的show()方法,但是show中调用play在student中有重写,所以最后打印student play System.out.println("------------------"); Student student = (Student) person;
student.show(); System.out.println("------------------"); student = new Monitor();
student.show();//monitor中有重写show,所以调用student.show()方法时(student中的show是继承自person),由于monitor有继承,调用monitor
              //的show()方法,但是monitor中show方法是调用super.show(),super中的show是调用play,最后还是打印Monitor的play }
}

运行结果:

student play
------------------
student play
------------------
Monitor play Process finished with exit code 0

【Java基础】Java中的多态的更多相关文章

  1. 第二十九节:Java基础知识-类,多态,Object,数组和字符串

    前言 Java基础知识-类,多态,Object,数组和字符串,回顾,继承,类的多态性,多态,向上转型和向下转型,Object,数组,多维数组,字符串,字符串比较. 回顾 类的定义格式: [类的修饰符] ...

  2. Java基础(中)

    面向对象基础 面向对象和面向过程的区别 两者的主要区别在于解决问题的方式不同: 面向过程把解决问题的过程拆成一个个方法,通过一个个方法的执行解决问题. 面向对象会先抽象出对象,然后用对象执行方法的方式 ...

  3. java基础---->java中正则表达式二

    跟正则表达式相关的类有:Pattern.Matcher和String.今天我们就开始Java中正则表达式的学习. Pattern和Matcher的理解 一.正则表达式的使用方法 一般推荐使用的方式如下 ...

  4. Java基础学习中一些词语和语句的使用

    在Java基础学习中,我们刚接触Java会遇到一些词和语句的使用不清的情况,不能很清楚的理解它的运行效果会是怎么样的,如:break,continue在程序中运行效果及跳转位置, 1.先来看看brea ...

  5. Java基础-Java中的堆内存和离堆内存机制

    Java基础-Java中的堆内存和离堆内存机制 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.

  6. Java基础-Java中的内存分配与回收机制

    Java基础-Java中的内存分配与回收机制 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一. 二.

  7. Java基础-Java中的并法库之重入读写锁(ReentrantReadWriteLock)

    Java基础-Java中的并法库之重入读写锁(ReentrantReadWriteLock) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 在学习Java的之前,你可能已经听说过读 ...

  8. Java基础-Java中的并法库之线程池技术

    Java基础-Java中的并法库之线程池技术 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.什么是线程池技术 二.

  9. Java基础-Java中23种设计模式之常用的设计模式

    Java基础-Java中23种设计模式之常用的设计模式 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.   一.设计模式分类 设计模式是针对特定场景给出的专家级的解决方案.总的来说设 ...

  10. Java基础-JAVA中常见的数据结构介绍

    Java基础-JAVA中常见的数据结构介绍 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.什么是数据结构 答:数据结构是指数据存储的组织方式.大致上分为线性表.栈(Stack) ...

随机推荐

  1. oracle expdp 无法导出SYS下特定TABLE

    创建测试表: D:\app\product\\db_1>sqlplus "/as sysdba" SQL :: Copyright (c) , , Oracle. All r ...

  2. hdu 3572 Task Schedule

    Task Schedule 题意:有N个任务,M台机器.每一个任务给S,P,E分别表示该任务的(最早开始)开始时间,持续时间和(最晚)结束时间:问每一个任务是否能在预定的时间区间内完成: 注:每一个任 ...

  3. 制作标签(Label)

    怎样判断是否应当使用标签 当游戏中出现需要程序输出文字的地方,就要使用标签. 创建标签 在Unity顶部选择NGUI菜单.选择Create->Label,即可创建一个Label. Label的文 ...

  4. classes system in sencha touch

    //http://www.sencha.com/learn/sencha-class-system var Person = new Ext.Class({ name: 'Mr. Unknown', ...

  5. 最近在折腾VPS(持续完善)

    买的某国内vps. 本机环境 Win7-x64 使用官方英文版的putty,用于远程登录linux主机.WinSCP图形界面管理文件. VPS CentOS 6.2 安装 安全狗(safedog.cn ...

  6. MUH and Cube Walls

    Codeforces Round #269 (Div. 2) D:http://codeforces.com/problemset/problem/471/D 题意:给定两个序列a ,b, 如果在a中 ...

  7. var a=[]; 和 var a=new Array(); 的区别,为什么前者效率高

    因为 JSON格式的语法是引擎直接解释的.而new Array 则需要调用Array的构造器.还有就是1.当你需要将一个数字转化为字符串时可以这样定义:var s=""+1; 这样 ...

  8. 数据库备份,远程执行SHELL脚本

    小小的东东,用于数据库的备份. 留存. #!/bin/sh keepDays= currentTime=`date "+%Y-%m-%d-%H-%M"` backPath=&quo ...

  9. easyui源码翻译1.32--LinkButton(按钮)

    前言 使用$.fn.linkbutton.defaults重写默认值对象.下载该插件翻译源码 按钮组件使用超链接按钮创建.它使用一个普通的<a>标签进行展示.它可以同时显示一个图标和文本, ...

  10. Linux伙伴系统1

    (一)--伙伴系统的概述 Linux内核内存管理的一项重要工作就是如何在频繁申请释放内存的情况下,避免碎片的产生.Linux采用伙伴系统解决外部碎片的问题,采用slab解决内部碎片的问题,在这里我们先 ...