Java基础之多态和泛型浅析

一、前言:

  楼主看了许多资料后,算是对多态和泛型有了一些浅显的理解,这里做一简单总结

二、什么是多态?

  多态(Polymorphism)按字面的意思就是“多种状态”。在面向对象语言中,接口(这里所谓的接口是楼主自己发明的,这里不是局限于Java的interface,可以把它看作为广义定义的对象源)的多种不同的实现方式即为多态。引用Charlie Calverts对多态的描述——多态性是允许你将父对象设置成为一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作(摘自“Delphi4 编程技术内幕”)。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。多态性在Object Pascal和C++中都是通过虚函数实现的。但是在Java中楼主认为基于类之间的继承关系
  多态指同一个实体同时具有多种形式。它是面向对象程序设计(OOP)的一个重要特征。如果一个语言只支持类而不支持多态,只能说明它是基于对象的,而不是面向对象的。C++中的多态性具体体现在运行和编译两个方面。运行时多态是动态多态,其具体引用的对象在运行时才能确定。编译时多态是静态多态,在编译时就可以确定对象使用的形式。
  简单的来说多态就是同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。在运行时,可以通过指向基类的指针,来调用实现派生类中的方法。
  把不同的子类对象都当作父类来看,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,以适应需求的不断变化。
  赋值之后,父类型的引用就可以根据当前赋值给它的子对象的特性以不同的方式运作。也就是说,父亲的行为像儿子,而不是儿子的行为像父亲。
  举个例子:从一个基类中派生,响应一个虚命令,产生不同的结果。
  比如从某个基类派生出多个子类,其基类有一个虚方法Tdoit,然后其子类也有这个方法,但行为不同,然后这些子类对象中的任何一个可以赋给其基类对象的引用,或者说将子对象地址赋给基类指针,这样其基类的对象就可以执行不同的操作了。实际上你是在通过其基类的引用来访问其子类对象的,你要做的就是一个赋值操作。
使用继承性的结果就是当创建了一个类的家族,在认识这个类的家族时,就是把子类的对象当作基类的对象,这种认识又叫作upcasting(向上转型)。这样认识的重要性在于:我们可以只针对基类写出一段程序,但它可以适应于这个类的家族,因为编译器会自动找出合适的对象来执行操作。这种现象又称为多态性。而实现多态性的手段又叫称动态绑定(dynamic binding)。
  简单的说,建立一个父类对象的引用,它所指对象可以是这个父类的对象,也可以是它的子类的对象。java中当子类拥有和父类同样的函数,当通过这个父类对象的引用调用这个函数的时候,调用到的是子类中的函数。
  多态,意味着一个对象有着多重特征,可以在特定的情况下,表现不同的状态,从而对应着不同的属性和方法。
 
 
  多态所展示的特性示例:
  Parent pa = new Child_A();
  pa.simpleCall()则显然是调用Child_A的方法;
  Parent pa = new Child_B();
  pa.simpleCall()则是在调用Child_B的方法。所以,我们对于抽象的父类或者接口给出了我们的具体实现后,pa 可以完全不用管实现的细节,只访问我们定义的方法,就可以了。事实上,这就是多态所起的作用,可以实现控制反转。这在大量的J2EE轻量级框架中被用到,比如Spring的依赖注入机制。

三、什么是泛型?

  一般的类和方法,只能使用具体的类型:要么是基本类型,要么是自定义的类。如果要编写可以应用多种类型的代码,这种刻板的限制对代码的约束就会很大。
  在面向对象编程语言中,上面介绍的多态是一种泛化机制。例如,你可以将方法的参数类型设为基类,那么,该方法就可以接受从这个基类中导出的任何类作为参数。这样的方法更加通用一些。可应用的地方也多一些。在类的内部也是如此,凡是需要说明类型的地方,如果都使用基类,确实能够具备很好的灵活性。但是如果考虑除了final类(不能扩展),其他任何类都可以被扩展,所以这种灵活性大多数也会有一些性能损耗。
  有时候,拘泥于单继承体系,也会使程序受限太多。如果方法的参数是一个接口,而不是一个类,这种限制就放松了许多。因为任何实现了该接口的都能够满足该方法,这也包括暂时还不存在的类
  在Java5之后,引入了泛型这个概念:泛型实现了参数化类型的概念,使代码可以应用于多种类型,泛型这个概念的术语是:“适用于许多许多的类型”。泛型通过解耦类或方法所使用的类型之间的约束。使类或方法具备最广泛的表达能力

   为什么要使用泛型?

  在Java5之前,泛型程序设计是用继承实现的。例如ArrayList类只维护一个Object引用的数组:

  //before generic classes

  public class ArrayList {

    private Object[] elementData;

    ...............

    public Object get(int i) {.......}

    public void add(Object object) {.........}

  }  

  这种方法有两个问题,当获取一个值时必须进行强制类型转换

  ArrayList files = new ArrayList();

  .......................

  String fileName = (String)files.get(0);

  此外,这里没有错误检查。可以向数组列表中添加任何类的对象。

  files.add(new File("......"));

  对于这个调用,编译和运行都不会出错。然而在其他地方,如果将get的结果强制类型转换为String类型,就会产生一个错误。泛型提供了一个更好的解决方案:

  Java5以后,ArrayList有一个类型参数来指定元素的类型:

  ArrayList<String> files = new ArrayList<String>();(在Java7及以后的版本中,构造函数中可以省略泛型类型:ArrayList<String> files = new ArrayList<>();)

  这显然使得代码具有更好的可读性。人们一看这个数组列表中包含的是String对象。

三、多态与泛型的区别:

  其实多态和泛型也没有什么根本的区别,如果非要说说区别,那就说说吧:

  泛型和多态比较容易混淆, 简单来说:泛型就是类型参数化, 好处是编译器会检查参数类型.多态就是多个类由继承(实现接口)得到的一致外观, 好处是简化代码, 隔绝修改实际上泛型和多态没有直接关系, 使用泛型在代码中就能按照指定类型的外观操作对象.

  比较常用的泛型类型就是List<T>和Map<T, T>, 说个简单的例子吧:

  List<String> list = ....; //具体类型, 就跟多态没什么关系了

  for (String str : list) {

    System.out.println(str.substring(1));

  }

  List<Animal> list = ...; //地球上但凡讲OO的都拿这个说事儿... 成员就是小猫小狗狮子老虎什么的

  for (Animal animal : list) {

     animal.say(); //喵, 汪....., 多态

  }

  多态可以分为编译时多态和运行时多态,泛型是对类型的抽象,属于编译时多态。

  比如说下面的私有字段x, 它的数据类型在编译的时候是动态决定的,具有多态性。

  class A<T>{ private T x;} A<string> a = new A<string>();

  多态还可以分为:行为多态和属性多态。

  下面的p在给它赋值前是不知道它的性别的,在给它赋不同的值的时候就表现出属性多态了。

  与此同时,也具有了行为的多态, Walk().男人和女人走路的方式是不一样的,所以是多态了。

  基类: Class Person, public virtual method Walk() {}

  子类: Man, Woman

     Person p = new Man();

     Person p = new Woman();

  转载请注明出处,谢谢!

Java基础之多态和泛型浅析的更多相关文章

  1. Java基础之Collection与Collections浅析

    Java基础之Collection与Collections浅析 一.前言: 位于Java.util包下的Collection与Collections都是Java中重要的工具类,它们都是Java集合框架 ...

  2. Java基础十一--多态

    Java基础十一--多态 一.多态定义 简单说:就是一个对象对应着不同类型. 多态在代码中的体现: 父类或者接口的引用指向其子类的对象. /* 对象的多态性. class 动物 {} class 猫 ...

  3. Java基础语法<十二> 泛型程序设计

    1 意义 泛型程序设计意味着编写的代码可以被很多不同类型的对象所重用. 常见应用 : ArrayList 2 K T V E ? object等的含义 类型变量使用大写形式 E – Element ( ...

  4. 【Java基础】多态

    首先先来个总结: 什么是多态 面向对象的三大特性:封装.继承.多态.从一定角度来看,封装和继承几乎都是为多态而准备的.这是我们最后一个概念,也是最重要的知识点. 多态的定义:指允许不同类的对象对同一消 ...

  5. Java基础之十五 泛型

    第十五章 泛型 一般的类和方法,只能使用具体的类型:要么是基本类型,要么是自定义类型.如果要编写可以应用于多种类型的代码,这种刻板的限制对代码的束缚就会很大. 在面对对象编程语言中,多态算是一种泛化机 ...

  6. Java基础之浅谈泛型

    简单的介绍了Java泛型类型的使用.上手容易,深入很难.

  7. 【java基础学习】-【泛型】

    参考以下几位同学的总结来学习: http://www.cnblogs.com/lwbqqyumidi/p/3837629.html#!comments http://www.weixueyuan.ne ...

  8. java基础之 多态

    在面向对象编程(Object-Oriented Programming, OOP)中,多态机制无疑是其最具特色的功能,甚至可以说,不运用多态的编程不能称之为OOP.这也是为什么有人说,使用面向对象语言 ...

  9. 黑马程序员——JAVA基础之多态与Object

    ------- android培训.java培训.期待与您交流! ----------  多态 : 多态定义:  某一类事物的多种存在形态. 多态的体现: 父类的引用指向了自己的子类对象.       ...

随机推荐

  1. Active Directory域

    引言 在 Microsoft® Windows® 2000 Server 操作系统的诸多增强功能中,Microsoft Active Directory™ 功能的引入意义最为重大,但也最常引起困惑.与 ...

  2. 通过ping命令了解三层转发流程

    ping命令:因特网包探索器.本文主要通过路由器两端不同网段PC互ping来讲解三层转发流程. 例子:PC-A是如何 ping 通 PC-C 的,有几种情况? 说明:1.在条件1阶段PC-C不会刷新a ...

  3. poj 1050 To the Max(最大子矩阵之和)

    http://poj.org/problem?id=1050 我们已经知道求最大子段和的dp算法 参考here  也可参考编程之美有关最大子矩阵和部分. 然后将这个扩大到二维就是这道题.顺便说一下,有 ...

  4. java并发之ConcurrentLinkedQueue

    在并发编程中,我们可能经常需要用到线程安全的队列,JDK提供了两种模式的队列:阻塞队列和非阻塞队列.阻塞队列使用锁实现,非阻塞队列使用CAS实现.ConcurrentLinkedQueue是一个基于链 ...

  5. 从原理层面掌握HandlerMethod、InvocableHandlerMethod、ServletInvocableHandlerMethod的使用【一起学Spring MVC】

    每篇一句 想当火影的人没有近道可寻,当上火影的人同样无路可退 前言 HandlerMethod它作为Spring MVC的非公开API,可能绝大多数小伙伴都对它比较陌生,但我相信你对它又不是那么的生疏 ...

  6. containerd与kubernetes集成

    kubernetes集群三步安装 概念介绍 cri (Container runtime interface) cri is a containerd plugin implementation of ...

  7. 一文读懂tomcat组件--一个web服务器的架构演化史

    1. tomcat是谁?     2. tomcat可以做什么? tomcat是一个web容器,可以将web应用部署到tomcat,由它提供web服务,一个web容器中可以部署多个web应用,这些we ...

  8. 带你剖析WebGis的世界奥秘----点和线的世界

    前言 昨天写了好久的博文我没保存,今天在来想继续写居然没了,气死人啊这种情况你们见到过没,所以今天重新写,我还是切换到了HTML格式的书写上.废话不多说了,我们现在就进入主题,上周我仔细研究了WebG ...

  9. 心里想的VS嘴上说的

    心里想的VS嘴上说的 背景:昨天开会,在招行总行那边,今天检讨下自己不会说话,真是太难了我! 一.昨日重现 现在回想起当时的场景觉得自己也真是搞笑,这都没死,太难了我.昨天下午在五楼开会,这也是我入职 ...

  10. Promise对象的resolve回调函数和reject回调函数使用

    Promise是ES6中用来结局回调地狱的问题的但是并不能帮我们减少代码量 Promise是一个构造函数 new Promise() 得到一个Promise一个实例 在Promise上有两个函数分别是 ...