Java泛型和反射机制课程安排Java泛型和反射机制JS和JQuery(CSS选择器,DOM,事件,Ajax和插件)JavaWeb拾遗补缺(项目开发常见问题分析和解决)Oracle高级SQL查询和性能优化基于Lucene/Solr的搜索技术课程目标Java泛型理解Java泛型应用Java泛型编程Java反射机制理解Java反射机制理解Java的动态代理SpringIoC原理剖析Java泛型在JavaSE1.5之前,没有泛型的情况的下,通过对类型Object的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者对实际参数类型可以预知的情况下进行的。对于强制类型转换错误的情况,编译器可能不提示错误,在运行的时候才出现异常,这是一个安全隐患。泛型是JavaSE1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。Java语言引入泛型的好处是简单安全:在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高代码的重用率。Java泛型:规则和限制1、泛型的类型参数只能是类类型(包括自定义类),不能是简单类型。2、同一种泛型可以对应多个版本(因为参数类型是不确定的),不同版本的泛型类实例是不兼容的。3、泛型的类型参数可以有多个。4、泛型的参数类型可以使用extends语句,例如Textendssuperclass。习惯上称为“有界类型”。5、泛型的参数类型还可以是通配符类型。例如Class?classType=Class.forName(java.lang.String);Demo:泛型与Object对比示例。Java泛型:泛型类语法泛型类的语法说明:使用T来声明一个类型持有者名称,就可以把T当作一个类型代表来声明成员、参数和返回值类型。T仅仅是个名字,这个名字可以自定义。声明classGenericsFooT声明了一个泛型类,这个T没有任何限制,实际上相当于Object类型,实际上相当于classGenericsFooTextendsObject。使用与Object泛型类相比,使用泛型所定义的类在声明和构造实例的时候,可以使用“实际类型”来一并指定泛型类型持有者的真实类型。比如GenericsFooDoubledouFoo=newGenericsFooDouble(newDouble(33));当然,也可以在构造对象的时候不使用尖括号指定泛型类型的真实类型,但是你在使用该对象的时候,就需要强制转换了。比如:GenericsFoodouFoo=newGenericsFoo(newDouble(33));实际上,当构造对象时不指定类型信息的时候,默认会使用Object类型,这也是要强制转换的原因。Java泛型:有界类型classGenericsFooTextendsCollection,这样类中的泛型T只能是Collection接口的实现类,传入非Collection接口编译会出错。注意:TextendsCollection这里的限定使用关键字extends,后面可以是类也可以是接口。但这里的extends已经不是继承的含义了,应该理解为T类型是实现Collection接口的类型,或者T是继承了XX类的类型。publicclassCollectionGenFooTextendsCollection{privateTx;publicCollectionGenFoo(Tx){this.x=x;}…getter/setter方法}实例化的时候可以这么写:publicclassCollectionGenFooDemo{publicstaticvoidmain(Stringargs[]){CollectionGenFooArrayListlistFoo=null;listFoo=newCollectionGenFooArrayList(newArrayList());//出错了,不让这么干。//CollectionGenFooCollectionlistFoo=null;//listFoo=newCollectionGenFooArrayList(newArrayList());System.out.println(实例化成功!);}}Java泛型:通配符泛型为了解决类型被限制死了不能动态根据实例来确定的缺点,引入了“通配符泛型”,针对上面的例子,使用通配泛型格式为?extendsCollection,“?”代表未知类型,这个类型是实现Collection接口。那么上面实现的方式可以写为:publicclassCollectionGenFooDemo{publicstaticvoidmain(Stringargs[]){CollectionGenFooArrayListlistFoo=null;listFoo=newCollectionGenFooArrayList(newArrayList());//现在不会出错了CollectionGenFoo?extendsCollectionlistFoo1=null;listFoo=newCollectionGenFooArrayList(newArrayList());System.out.println(实例化成功!);}}说明:1、如果只指定了?而没有extends,则默认是允许Object及其下的任何Java类了。也就是任意类。2、通配符泛型不单可以向下限制,如?extendsCollection,还可以向上限制,如?superDouble,表示类型只能接受Double及其上层父类类型,如Number、Object类型的实例。3、泛型类定义可以有多个泛型参数,中间用逗号隔开,还可以定义泛型接口,泛型方法。这些都泛型类中泛型的使用规则类似。Java泛型:泛型方法是否拥有泛型方法,与其所在的类是否泛型没有关系。要定义泛型方法,只需将泛型参数列表置于返回值前。如:publicclassExampleA{publicTvoidf(Tx){System.out.println(x.getClass().getName());}}使用泛型方法时,不必指明参数类型,编译器会自己找出具体的类型。泛型方法除了定义不同,调用就像普通方法一样。Java泛型应用示例/**DAO操作基类:本DAO层实现了通用的数据操作*@paramTPOJO实体对象*@paramIDID*/publicclassBaseHibernateDAOImplT,IDextendsSerializableextendsHibernateDaoSupportimplementsBaseHibernateDaoT,ID{privateClassTentityClass;publicvoidsetEntityClass(ClassTentityClass){this.entityClass=entityClass;}…}Java语言的反射机制在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法?答案是肯定的。这种动态获取类的信息,以及动态调用对象的方法的功能来自于Java语言的反射(Reflection)机制。Java反射机制主要提供了以下功能:在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。JavaReflectionAPI在JDK中,主要由以下类来实现Java反射机制,这些类都位于java.lang.reflect包中:Java.lang.Class类:代表一个类。Field类:代表类的成员变量(成员变量也称为类的属性)。Method类:代表类的方法。Constructor类:代表类的构造方法。Array类:提供了动态创建数组,以及访问数组元素的静态方法。例1:DumpMethods列出类的方法列表例2:ReflectTester对象属性值拷贝的实现例3:InvokeTester通过反射机制调用add,echo方法JavaReflectionAPIimportjava.lang.reflect.*;publicclassInvokeTester{publicintadd(intparam1,intparam2){returnparam1+param2;}publicStringecho(Stringmsg){return“echo:”+msg;}publicstaticvoidmain(String[]args)throwsException{ClassclassType=InvokeTester.class;ObjectinvokeTester=classType.newInstance();//调用InvokeTester对象的add()方法MethodaddMethod=classType.getMethod(add,newClass[]{int.class,int.class});Objectresult=addMethod.invoke(invokeTester,newObject[]{newInteger(100),newInteger(200)});System.out.println((Integer)result);//调用InvokeTester对象的echo()方法MethodechoMethod=classType.getMethod(echo,newClass[]{String.class});result=echoMethod.invoke(invokeTester,newObject[]{Hello});System.out.println((String)result);}}JavaReflectionAPIMethod类的invoke(Objectobj,Objectargs[])方法用于动态执行一个对象的特定方法。第一个obj参数指定具有该方法的对象;第二个args参数指定向该方法传递的参数,该参数必须为对象,如果参数为基本类型数据,必须转换为相应的包装类型的对象;invoke()方法的返回值总是对象,如果实际被调用的方法的返回类型是基本类型数据,那么invoke()方法会把它转换为相应的包装类型的对象,再将其返回。代理模式代理模式是常用的Java设计模式,它的特征是代理类与委托类有同样的接口。代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。按照代理类的创建时期,代理类可分为两种。静态代理类:由程序员创建或由特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。动态代理类:在程序运行时,运用反射机制动态创建而成。图:代理模式静态代理类如图a所示,HelloServiceProxy类是代理类,HelloServiceImpl类是委托类,这两个类都实现了HelloService接口。其中HelloServiceImpl类是HelloService接口的真正实现者,而HelloServiceProxy类是通过调用HelloServiceImpl类的相关方法来提供特定服务的。HelloServiceProxy类的echo()方法和getTime()方法会分别调用被代理的HelloServiceImpl对象的echo()方法和getTime()方法,并且在方法调用前后都会执行一些简