多态性

在面向对象中多态性实际上是面向对象里的一个最大的最有用的特点,对于多态性在java中有两种体现:

1、  方法的重载及覆写

2、  对象多态性:指的是父类对象和子类对象之间的转型操作

一、对象多态性:

继承允许将对象视为它本身或者它的父类的类型来处理,即将继承自同一父类的基类可以视为同一类处理,一份代码就可以毫无差别的运行在这些不同类型上。多态方法调用允许一种类型表现出与其他相似类型之间的区别,只要它们是从同一基类导出的。虽然这些方法都通过基类调用。

实现原理:后期绑定:在运行时根据对象的类型进行绑定。后期绑定也称为多态绑定或者运行时绑定。

Java中除了static方法和final方法(private方法属于final方法),其他的方法都是后期绑定。

只有普通方法调用时多态的。

对象多态性的例子

基类,形状类 Shape.java

public class Shape {public void draw() {}public void erase() {}
}

子类1,圆形 Circle.java

public class Circle extends Shape {public void draw() { System.out.println("Circle.draw()"); }public void erase() { System.out.println("Circle.erase()"); }
}

子类2,三角形 Triangle.java

public class Triangle extends Shape {public void draw() { System.out.println("Triangle.draw()"); }public void erase() { System.out.println("Triangle.erase()"); }
} 

子类3,正方形 Square.java

public class Square extends Shape {public void draw() { System.out.println("Square.draw()"); }public void erase() { System.out.println("Square.erase()"); }
}

多态性体现

public class Shapes {public static void main(String[] args) {Shape shape1 = new Circle();Shape shape2 = new Triangle();Shape shape3 = new Square();shape1.draw();shape2.draw();shape3.draw();}
}
/* Output:
Circle.draw()
Triangle.draw()
Square.draw()
*/

二、多态性理解:

2.1只有非私有方法才可以被覆盖

“覆盖”私有方法:

class PrivateOverride {private void f() {System.out.println("privatef()");}}public class Derived extends PrivateOverride {public void f() {System.out.println("publicf()");}public static void main(String[] args) {PrivateOverride po = new Derived();po.f();//异常The method f() from the type PrivateOverride is not visible}}

例子2:覆盖私有方法的现象,编译器不报错,但是不会按照我们期望的执行。

public class PrivateOverride {private void f() {System.out.println("private f()");}public static void main(String[] args) {PrivateOverride po = new Derived();po.f();}}class Derived extends PrivateOverride {public void f() {System.out.println("public f()");}}/** Output: private f()*/

2.2、父类和子类有相同的属性,且为public的情况

只有普通方法的调用时多态的,如果访问某一个成员变量,该成员变量是public的,且父类子类都有这个属性,它的访问是在编译期进行解析。

虽然发生向上转型,Super sup = new Sub();sup.field就没有多态性,访问的是父类的field。

class Super {public int field = 0;public int getField() {return field;}
}class Sub extends Super {public int field = 1;public int getField() {return field;}public int getSuperField() {return super.field;}
}public class FieldAccess {public static void main(String[] args) {Super sup = new Sub(); // UpcastSystem.out.println("sup.field = " + sup.field + ", sup.getField() = "+ sup.getField());Sub sub = new Sub();System.out.println("sub.field = " + sub.field + ", sub.getField() = "+ sub.getField() + ", sub.getSuperField() = "+ sub.getSuperField());}
}
/* Output:
sup.field = 0, sup.getField() = 1
sub.field = 1, sub.getField() = 1, sub.getSuperField() = 0
*/

2.3静态方法不具有多态性

如果某一个方法是静态的,它的行为就不具有多态性。

class StaticSuper {public static String staticGet() {return "Base staticGet()";}public String dynamicGet() {return "Base dynamicGet()";}
}class StaticSub extends StaticSuper {public static String staticGet() {return "Derived staticGet()";}public String dynamicGet() {return "Derived dynamicGet()";}
}public class StaticPolymorphism {public static void main(String[] args) {StaticSuper sup = new StaticSub(); // UpcastSystem.out.println(sup.staticGet());//静态方法,调用子类的System.out.println(sup.dynamicGet());//非静态方法}
}
/** Output: Base staticGet() Derived dynamicGet()*/

三、构造器内部调用的方法被子类覆盖的情况

构造器内部调用的方法被子类覆盖了。这个调用的效果很难预料,因为被覆盖的方法在对象被完全构造之前就会调用。这一定会造成一些难以发现的错误。

class Glyph {void draw() {System.out.println("Glyph.draw()");}Glyph() {System.out.println("Glyph() before draw()");draw();System.out.println("Glyph() after draw()");}
}class RoundGlyph extends Glyph {private int radius = 1;RoundGlyph(int r) {radius = r;System.out.println("RoundGlyph.RoundGlyph(), radius = " + radius);}void draw() {System.out.println("RoundGlyph.draw(), radius = " + radius);}
}public class PolyConstructors {public static void main(String[] args) {new RoundGlyph(5);}
}
/* Output:
Glyph() before draw()
RoundGlyph.draw(), radius = 0
Glyph() after draw()
RoundGlyph.RoundGlyph(), radius = 5
*/

输出结果显示当Glyph的构造器调用draw()方法时候,radius不是默认初始值1而是0。

仔细分析这段代码,可以发现

1.在其他任何事物发生之前,将分配给对象的存储空间初始化成二进制的零。

2.如前所述那样调用基类构造器,此时,调用被覆盖后的draw()方法(注意,要在调用RoundGlyph构造器之前调用),由于步骤1的缘故,我们此时会发现radius的值为0

3.按照声明的顺序调用成员的初始化方法。

4调用导出类的构造器主体

这样有一个优点,至少保证所有的东西初始化为零或者null,而不仅仅是垃圾。其中通过‘组合’而嵌入到一个类内部的对象引用,其值是null,如果忘记为该值进行初始化,均会在运行时候出现异常。查看结果时候,发现其他所有的东西都是0.

结论:编写构造器的准则

用尽可能简单的方法使对象进入正常状态,可以的话,避免调用其他的方法。构造器内唯一能够安全调用的方法是基类中的final方法(也适用于private,它们自动属于final方法),这些方法不能被覆盖,因此也不会出现上述令人惊讶的问题。

四、向上转型

发生向上转型后,子类中自己的定义的操作是无法通过父类对象找到的。

class Useful {public void f() {}public void g() {}
}class MoreUseful extends Useful {public void f() {}public void g() {}public void u() {}public void v() {}public void w() {}}public class RTTI {public static void main(String[] args) {Useful[] x = { new Useful(), new MoreUseful() };x[0].f();x[1].g();
//      x[1].u();// 编译错误 The method u() is undefined for the type Useful((MoreUseful) x[1]).u(); // ((MoreUseful) x[0]).u(); // 必须现有upCast才能有downCast,错误的向下转型,java.lang.ClassCastException}}

java基础----多态性相关推荐

  1. Java基础-我所理解的泛型

    Java基础-我所理解的泛型 引用 [java]泛型中,? extends T 与 ? super T 的区别.看法_winrh的博客-CSDN博客_泛型 extends 前言 Java基础系列,我所 ...

  2. java 多态判断非空_跳槽涨薪季面试题之java基础(一)

    点击上方[全栈开发者社区]→右上角[...]→[设为星标⭐] 为迎接金九银十跳槽涨薪季,小编汇总了java精编版面试题,大概从java基础.java8特性.多线程.spring.springboot. ...

  3. 【转】Java基础知识整理

    本博文内容参考相关博客以及<Java编程思想>整理而成,如有侵权,请联系博主. 转载请注明出处:http://www.cnblogs.com/BYRans/ PDF版下载链接:<Ja ...

  4. 100道Java基础面试题收集整理(附答案)

    不积跬步无以至千里,这里会不断收集和更新Java基础相关的面试题,目前已收集100题. 1.什么是B/S架构?什么是C/S架构 B/S(Browser/Server),浏览器/服务器程序 C/S(Cl ...

  5. java基础总结(小白向)

    java入门基础总结(小白向) 1.类和对象的理解 ​ 理解类和对象对应学习Java尤其重要,可以说类和对象贯穿整个Java语言.我们先给出类和对象比较官方的介绍. ​ 类:具有相同属性和方法的一组对 ...

  6. java 基础知识总结

    Java基础知识总结 写代码: 1,明确需求.我要做什么? 2,分析思路.我要怎么做?1,2,3. 3,确定步骤.每一个思路部分用到哪些语句,方法,和对象. 4,代码实现.用具体的java语言代码把思 ...

  7. Java基础之多态深入解析

    Java基础之多态深入解析 多态的基本概念 同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果,这就是多态性.简单的说:就是用基类的引用指向子类的对象. 多态的优点 消除类型之间的耦合关系 ...

  8. Java基础知识回顾之七 ----- 总结篇

    前言 在之前Java基础知识回顾中,我们回顾了基础数据类型.修饰符和String.三大特性.集合.多线程和IO.本篇文章则对之前学过的知识进行总结.除了简单的复习之外,还会增加一些相应的理解. 基础数 ...

  9. java实体类转map_十五道经典面试题-JAVA基础篇

    十五道JAVA基础面试题送给有需要的童鞋,但是不得不多提醒一句,打铁还需自身硬,计算机软件这个行业,技术和学历才是王道.好了,废话不多说,上菜: 一:面向对象的特征有哪些方面 1. 抽象:抽象就是忽略 ...

最新文章

  1. 为什么数学的用途这么大?
  2. Sublime如何设置背景透明
  3. linux判断网卡是否挂载,检查网卡是否加载 - Linux服务器网卡驱动安装及故障排除_服务器应用_Linux公社-Linux系统门户网站...
  4. LeetCode Construct Binary Tree from Preorder and Inorder Traversal(构造二叉树)
  5. php 二维数组去重
  6. protel99se 问题汇总(不定期更新)
  7. sklearn 安装_初识sklearn
  8. 程序员面试问题资源经验
  9. IIS安装和ASP.NET Web应用程序开发期间部署到IIS自定义主机域名并附加进程调试...
  10. 将Session写入数据库
  11. 秒表的检定及设备使用方法说明
  12. 全链路压测之全链自动化
  13. IOCCC.1987.korn.c.解析
  14. 大数定律、中心极限定理总结
  15. Ubuntu下安装Qt
  16. pd调节规律_PID调节规律总结
  17. 雷军第二场直播带货圆满成功,雷军代言小米试用期一个月
  18. 一维正态分布的最大似然估计
  19. 路由协议(实例讲解)
  20. linux c++ 文件修改时间,linux下C获取系统时间的方法

热门文章

  1. org.springframework.cloud.client.loadbalancer.LoadBalancedRetryPolicyFactory---springcloud工作笔记162
  2. OAuth2.0_授权服务配置_密码模式及其他模式_Spring Security OAuth2.0认证授权---springcloud工作笔记145
  3. 项目业务工作笔记001---发改委职责
  4. 政务外网001---政务外网介绍
  5. Rpc远程调用框架的设计与实现(1)
  6. WSAGetLastError() 返回的错误
  7. 爬取新笔趣阁排行并保存到mysql_python+selenium爬取微博热搜存入Mysql的实现方法...
  8. 用计算机坑人,10大坑人专业,坑你没商量!
  9. win32开发(图形绘制)
  10. 教师提升微能力_国培主讲风采录:信息技术再提升 微能力点巧研修