第14讲 反射与注释_第1页
第14讲 反射与注释_第2页
第14讲 反射与注释_第3页
第14讲 反射与注释_第4页
第14讲 反射与注释_第5页
已阅读5页,还剩97页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、回顾lWeb服务简介l常用应用开发环境介绍lJSP要素lServlet要素l组件技术与java beanlJsp设计模式课程内容l类加载l类加载过程l类加载委托模型l类加载测试l反射lJava反射机制l代理模式类的初始化l类的加载l加载类的.class文件,并创建该类的java.lang.class对象l类的连接l验证:.class文件是否正确结构l准备:为静态属性分配内存并设置初始值l解析:将类的二进制数据中的符号引用替换为直接引用l类的初始化l静态属性的初始化类初始化的时机l创建类的实例l调用类的静态方法l访问类或接口的静态属性,或者为静态属性赋值l利用反射方式强制创建类或接口 对应的ja

2、va.lang.class对象l初始化某子类时,该子类的父类都会被初始化。l直接使用java虚拟机运行某一个主类时,程序会初始化该主类lOther:lfinal的静态属性如果在编译时能获得值,那么调用该属性不会引起类的初始化,如果该属性需要运行才能获得,那么会引起类的初始化类的加载器l类加载器(Classloader)负责将.class文件加载到内存中并为之生成对应的java.lang.Class对象。lJvm中的三个类加载器lbootstrap class loader,负责加载系统类,比如jdk的rt.jar包里的类。lextension class loader,负责加载jre/lib/

3、ext目录下的所有类。 lsystem class loader,负责加载环境变量classpath指向目录下的所有类。 类的加载机制l缓存机制l加载的类存储在虚拟机的缓存中,当程序需要某一个类时会先在缓存中查找,如果查找不到再去加载.class文件l全盘责任l如果一个类由某一个类加载器加载,那么所有该类相关的类均由此类加载器加载,除非显式的使用其它类加载器l父类委托l先由父类加载器加载,如果不成功再使用子类加载器类加载器委托模型l类别加载器有加载类别的需求时,会先请其Parent帮忙加载l如果Parent找不到,那么才有自己按照自己的搜索路径搜索类别l搜索路径lBootstrap(sun.b

4、oot.class.path,预设 不能改变)lExtClassLoader(可通过-Djava.ext.dirs改变)lAppClassLoader(-classpath cp来改变 或设置CLASSPATH)类的加载过程l1.检测此Class是否载入过(即在cache中是否有此Class),如果有到8,如果没有到22.如果parent classloader不存在(没有parent,那parent一定是bootstrap classloader了),到43.请求parent classloader载入,如果成功到8,不成功到54.请求jvm从bootstrap classloader中载入

5、,如果成功到85.寻找Class文件(从与此classloader相关的类路径中寻找)。如果找不到则到7.6.从文件中载入Class,到8.7.抛出ClassNotFoundException.8.返回Class.l其中5.6步可以重写ClassLoader相关方法来实现自己的载入策略系统启动及初始化系统启动及初始化l当我们在命令行中输入java xxx.class的时候 java.exe会找到JRE,然后找到JRE中的jvm.dll(虚拟机),并启动java虚拟机l初始化(获取系统参数)l产生第一个classLoader即Bootstrap ClassLoader(C+编写,以java的观点

6、来看,逻辑上并不存在Bootstrap Loader的实体).lBootstrap初始化 载入sun.misc命名空间下的Launcher.java中的ExtClassLoader,并设置其parent为null,表示其父类别加载器为Bootstrap ClassLoaderlBootstrap 继续载入Launcher.java中的AppClassLoader,并设置其parent为ExtClassLoader类加载示例Test.javapublic class testpublic static void main(String args)System.out.println(test.c

7、lass.getClassLoader() ;testlib tl = new testlib() ;tl.print() ;testlib.javapublic class testlibpublic void print()System.out.println(this.getClass().getClassLoader() ;类加载测试一JRE所在目录classes下Test.classtestLib.classJRE所在目录libextclasses下Test.classtestLib.classD:my下Test.classtestLib.class输出结果输出结果:类加载测试二JR

8、E所在目录classes下Test.classJRE所在目录libextclasses下Test.classtestLib.classD:my下Test.classtestLib.class输出结果输出结果:结论是结论是?类加载测试三JRE所在目录classes下testLib.classJRE所在目录libextclasses下Test.classtestLib.classD:my下Test.classtestLib.class输出结果输出结果:结论是结论是?类加载测试四JRE所在目录classes下JRE所在目录libextclasses下Test.classtestLib.classD:

9、my下Test.classtestLib.class输出结果输出结果:结论是结论是?类加载测试五JRE所在目录classes下JRE所在目录libextclasses下Test.classD:my下Test.classtestLib.class输出结果输出结果:结论是结论是?类加载测试六JRE所在目录classes下JRE所在目录libextclasses下testlib.classD:my下Test.classtestLib.class输出结果输出结果:结论是结论是?类加载测试七JRE所在目录classes下JRE所在目录libextclasses下D:my下Test.classtestLi

10、b.class输出结果输出结果:结论是结论是?类的加载机制l全盘责任l如果一个类由某一个类加载器加载,那么所有该类相关的类均由此类加载器加载,除非显式的使用其它类加载器l父类委托l先由父类加载器加载,如果不成功再使用子类加载器自己创建类加载器lClassLoader的方法的方法 lloadClass l调用 findLoadedClass(String) 来检查是否已经加载类。l在父类加载器上调用 loadClass 方法。如果父类加载器为 null,则使用虚拟机的内置类加载器。 l调用 findClass(String) 方法查找类。 lfindSystemClass方法从本地文件系统中寻找

11、类文件,如果存在,就使用defineClass将原始字节转换成Class对象,以将该文件转换成类。lresolveClass 可以不完全地(不带解析)装入类,也可以完全地(带解析)装入类。当编写我们自己的loadClass时可以调用resolveClass,这取决于loadClass的resolve参数的值。 lfindLoadedClass充当一个缓存:当请求loadClass装入类时,它调用该方法来查看ClassLoader是否已装入这个类,这样可以避免重新装入已存在类所造成的麻烦 Tomcat的类载入器的结构 lTomcat Server在启动的时候将构造一个ClassLoader树,以

12、保证模块的类库是私有的- Bootstrap - 载入JVM自带的类和$JAVA_HOME/jre/lib/ext/*.jar- System - 载入$CLASSPATH/*.class- Common - 载入$CATALINA_HOME/common/.,它们对TOMCAT和所有的WEB APP都可见- Catalina - 载入$CATALINA_HOME/server/.,它们仅对TOMCAT可见,对所有的WEB APP都不可见- Shared - 载入$CATALINA_HOME/shared/.,它们仅对所有WEB APP可见,对TOMCAT不可见(也不必见)- WebApp?

13、- 载入ContextBase?/WEB-INF/.,它们仅对该WEB APP可见 Java反射机制lJava反射机制l代理模式动态语言l“程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”。从这个观点看,Perl,Python,Ruby是动态语言,C+,Java,C#不是动态语言。l尽管在这样的定义与分类下Java不是动态语言,它却有着一个非常突出的动态相关机制:Reflection。什么是反射l反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。lJAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和

14、方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。Java 语言的反射机制l在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法?答案是肯定的。这种动态获取类的信息以及动态调用对象的方法的功能来自于Java 语言的反射(Reflection)机制。lJava 反射机制主要提供了以下功能Java 语言的反射机制l在运行时判断任意一个对象所属的类。l在运行时构造任意一个类的对象。l在运行时判断任意一个类所具有的成员变量和方法。l在运行时调用任意一个对象的方法Ja

15、va 语言的反射机制lReflection 是Java被视为动态语言的一个关键性质。这个机制允许程序在运行时透过Reflection APIs取得任何一个已知名称的class的内部信息,包括其modifiers(诸如public, static 等等)、superclass(例如Object)、实现的interfaces(例如Serializable),也包括fields和methods的所有信息,并可于运行时改变fields内容或调用methodsJava Reflection API 简介l在JDK中,主要由以下类来实现Java反射机制,这些类都位于java.lang.reflect包中l

16、Class类:代表一个类。lField 类:代表类的成员变量(成员变量也称为类的属性)。lMethod类:代表类的方法。lConstructor 类:代表类的构造方法。“Class” class 众所周知Java有个Object class,是所有Java classes的继承根源,其内声明了数个应该在所有Java class中被改写的methods:hashCode()、equals()、clone()、toString()、getClass()等。其中getClass()返回一个Class object。“Class” class Class是Reflection起源。针对任何您想探勘的c

17、lass,唯有先为它产生一个Class object,接下来才能经由后者唤起为数十多个的Reflection APIs“Class” object的取得途径lJava允许我们从多种途径为一个class生成对应的Class object“Class” object的取得途径Java Reflection API 简介l在java.lang.Object 类中定义了getClass()方法,因此对于任意一个Java对象,都可以通过此方法获得对象的类型。Class类是Reflection API 中的核心类,它有以下方法lgetName():获得类的完整名字。lgetFields():获得类的pub

18、lic类型的属性。lgetDeclaredFields():获得类的所有属性。lgetMethods():获得类的public类型的方法。lgetDeclaredMethods():获得类的所有方法。Reflectionl获取域的值 SampleGet.javaRectangle r = new Rectangle(100,325);Class c = r.getClass();heightField = c.getField(height);heightValue = (Integer) heightField.get(r);取取r对象的对象的height值值基本数据类基本数据类型使用封装型

19、使用封装类类Reflectionl设置域的值 SampleSet.javawidthField = c.getField(width);widthField.set(r,widthParam);改变r对象的width值Object基本类型Java Reflection API 简介lgetMethod(String name, Class parameterTypes):获得类的特定方法,name参数指定方法的名字,parameterTypes 参数指定方法的参数类型。lgetConstructors():获得类的public类型的构造方法。lgetConstructor(Class para

20、meterTypes):获得类的特定构造方法,parameterTypes 参数指定构造方法的参数类型。lnewInstance():通过类的不带参数的构造方法创建这个类的一个对象。Java Reflection API 简介l2)通过默认构造方法创建一个新对象:lObject objectCopy=classType.getConstructor(new Class).newInstance(new Object);l以上代码先调用Class类的getConstructor()方法获得一个Constructor 对象,它代表默认的构造方法,然后调用Constructor对象的newInsta

21、nce()方法构造一个实例。Reflectionl使用 Constructor带参数方法l例 SampleInstance.javaJava Reflection API 简介l(3)获得对象的所有属性:lField fields=classType.getDeclaredFields();lClass 类的getDeclaredFields()方法返回类的所有属性,包括public、protected、默认和private访问级别的属性Reflectionl调用方法 SampleInvoke.java调用obj参数为args的方法import java.lang.reflect.*;publ

22、ic class InvokeTester public int add(int param1,int param2)return param1+param2;public String echo(String msg)return “echo:”+msg;public static void main(String args) throws ExceptionClass classType=InvokeTester.class;Object invokeTester=classType.newInstance();/调用调用InvokeTester对象的对象的add()方法方法Method

23、addMethod=classType.getMethod(add,new Classint.class,int.class);Object result=addMethod.invoke(invokeTester,new Objectnew Integer(100),new Integer(200);System.out.println(Integer)result);/调用调用InvokeTester对象的对象的echo()方法方法Method echoMethod=classType.getMethod(echo,new ClassString.class);result=echoMet

24、hod.invoke(invokeTester,new ObjectHello);System.out.println(String)result);Java Reflection API 简介 在例程InvokeTester类的main()方法中,运用反射机制调用一个InvokeTester对象的add()和echo()方法Java Reflection API 简介ladd()方法的两个参数为int 类型,获得表示add()方法的Method对象的代码如下:lMethod addMethod=classType.getMethod(add,new Classint.class,int.cl

25、ass);lMethod类的invoke(Object obj,Object args)方法接收的参数必须为对象,如果参数为基本类型数据,必须转换为相应的包装类型的对象。invoke()方法的返回值总是对象,如果实际被调用的方法的返回类型是基本类型数据,那么invoke()方法会把它转换为相应的包装类型的对象,再将其返回Java Reflection API 简介l尽管InvokeTester 类的add()方法的两个参数以及返回值都是int类型,调用add Method 对象的invoke()方法时,只能传递Integer 类型的参数,并且invoke()方法的返回类型也是Integer 类

26、型,Integer 类是int 基本类型的包装类:lObject result=addMethod.invoke(invokeTester,lnew Objectnew Integer(100),new Integer(200);lSystem.out.println(Integer)result); /result 为Integer类型Java反射的应用lSpring框架:IOC(控制反转)lHibernate框架:关联映射等l白盒测试Classl类是程序的一部分,每个类都有一个Class对象。换言之,每当编写并且编译了一个新类,就会产生一个Class对象lClass 没有公共构造方法。Cl

27、ass 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的,因此不能显式地声明一个Class对象lClass是Reflection起源。要想操纵类中的属性和方法,都必须从获取Class object开始l第一个实例就用大家非常熟悉的ArrayList类,我们尝试来获取ArrayList申明的方法。public static void main(String args) ArrayList aList = new ArrayList(); Class alClass = aList.getClass();System.out.println(+a

28、lClass);System.out.println(+alClass.getName();Method alMethod = alClass.getDeclaredMethods();for(Method method : alMethod)System.out.println(+method);System.out.println(+method.getName();第一步永远是获得被反射类的第一步永远是获得被反射类的ClassClass对象!对象!案例一获取Class Object获取方式获取方式说明说明示例示例object.getClass()每个对象都有此方法获取指定实例对象的Cla

29、ssList list = new ArrayList();Class listClass = list.getClass();class. getSuperclass()获取当前Class的继承类ClassList list = new ArrayList();Class listClass = list.getClass();Class superClass = listClass. getSuperclass();Object.class.class直接获取Class listClass = ArrayList.class;Class.forName(类名)用Class的静态方法,传入类

30、的全称即可try Class c = Class.forName(java.util.ArrayList); catch (ClassNotFoundException e) e.printStackTrace();Primitive.TYPE基本数据类型的封装类获取Class的方式Class longClass = Long.TYPE;Class integerClass = Integer.TYPE;Class voidClass = Void.TYPE;通过反射实例化对象l平常情况我们通过new Object来生成一个类的实例,但有时候我们没法直接new,只能通过反射动态生成。l实例化无

31、参构造函数的对象,两种方式:Class. newInstance();Class. getConstructor (new Class).newInstance(new Object)l实例化带参构造函数的对象:Class. getConstructor(Class. parameterTypes) . newInstance(Object. initargs) 案例准备l新建一个JavaBeanUser,User继承自另一个BeanBaseUser。注意:这两个Bean的属性和方法的作用域!案例二:动态实例化通过反射调用方法l获得当前类以及超类的public Method:Method ar

32、rMethods = classType. getMethods();l获得当前类申明的所有Method:Method arrMethods = classType. getDeclaredMethods();l获得当前类以及超类指定的public Method:Method method = classType. getMethod(String name, Class. parameterTypes);l获得当前类申明的指定的Method:Method method = classType. getDeclaredMethod(String name, Class. parameterTy

33、pes) l通过反射动态运行指定Method:Object obj = method. invoke(Object obj, Object. args) 案例三:动态操纵Method2010-12-2第53页成都天府软件园有限公司TOSC-ITO通过反射调用变量l获得当前类以及超类的public Field:Field arrFields = classType. getFields();l获得当前类申明的所有Field:Field arrFields = classType. getDeclaredFields();l获得当前类以及超类指定的public Field:Field field

34、= classType. getField(String name);l获得当前类申明的指定的Field:Field field = classType. getDeclaredField(String name); l通过反射动态设定Field的值:fieldType.set(Object obj, Object value);l通过反射动态获取Field的值: Object obj = fieldType. get(Object obj) ;案例四:动态操纵Field2010-12-2第55页成都天府软件园有限公司TOSC-ITOJava反射总结l只要用到反射,先获得Class Objec

35、tl没有方法能获得当前类的超类的private方法和属性,你必须通过getSuperclass()找到超类以后再去尝试获得l通常情况即使是当前类,private属性或方法也是不能访问的,你需要 设置压制权限setAccessible(true)来取得private的访问权。但说实话,这已经破坏了面向对象的规则,所以除非万不得已,请尽量少用。 目录lJava反射机制l代理模式代理模式l代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。l在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用代理模式l代理模式一般涉及到的角色有 l抽象

36、角色:声明真实对象和代理对象的共同接口l代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装l真实角色:代理角色所代表的真实对象,是我们最终要引用的对象动态代理类lJava动态代理类位于java.lang.reflect包下,一般主要涉及到以下两个类: l(1)Interface InvocationHandler:该接口中仅定义了一个方法lpublic object invoke(Object obj,Method method

37、, Object args)l在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,如上例中的request(),args为该方法的参数数组。 这个抽象方法在代理类中动态实现。 l(2)Proxy:该类即为动态代理类,作用类似于上例中的ProxySubject,其中主要包含以下内容动态代理类lprotected Proxy(InvocationHandler h):构造函数,用于给内部的h赋值。 lstatic Class getProxyClass (ClassLoader loader, Class interfaces):获得一个代理类,其中loader是类装载器,i

38、nterfaces是真实类所拥有的全部接口的数组。 lstatic Object newProxyInstance(ClassLoader loader, Class interfaces, InvocationHandler h):返回代理类的一个实例,返回后的代理类可以当作被代理类使用(可使用被代理类的在Subject接口中声明过的方法)动态代理类l通过这种方式,被代理的对象(RealSubject)可以在运行时动态改变,需要控制的接口(Subject接口)可以在运行时改变,控制的方式(DynamicSubject类)也可以动态改变,从而实现了非常灵活的动态代理关系动态代理步骤动态代理步骤

39、l1.创建一个实现接口InvocationHandler的类,它必须实现invoke方法l2.创建被代理的类以及接口l3.通过Proxy的静态方法lnewProxyInstance(ClassLoader loader, Class interfaces, InvocationHandler h) 创建一个代理l4.通过代理调用方法代理模式代理模式是常用的代理模式是常用的Java 设计模式,它的特征是代理类与委托类有同样的接口。代设计模式,它的特征是代理类与委托类有同样的接口。代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后理类主要负责为委托类预处理消息、过滤消息、把消

40、息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。类的对象的相关方法,来提供特定的服务。按照代理类的创建时期,代理类可分为两种。按照代理类的创建时期,代理类可分为两种。静态代理类静态代理类:由程序员创建或由特定工具自动生成源代码,再对其编译。在程序:由程序员创建或由特定工具自动生成源代码,再对其编译。在程序

41、运行前,代理类的运行前,代理类的.class文件就已经存在了。文件就已经存在了。动态代理类动态代理类:在程序运行时,运用反射机制动态创建而成。:在程序运行时,运用反射机制动态创建而成。图图: 代理模式代理模式静态代理类如图如图a所示,所示,HelloServiceProxy 类是代理类,类是代理类,HelloServiceImpl类是委托类,这类是委托类,这两个类都实现了两个类都实现了HelloService接口。其中接口。其中HelloServiceImpl类是类是HelloService接口接口的真正实现者,而的真正实现者,而HelloServiceProxy类是通过调用类是通过调用Hel

42、loServiceImpl 类的相关方类的相关方法来提供特定服务的。法来提供特定服务的。HelloServiceProxy类的类的echo()方法和方法和getTime()方法会分别方法会分别调用被代理的调用被代理的HelloServiceImpl 对象的对象的echo()方法和方法和getTime()方法,并且在方法方法,并且在方法调用前后都会执行一些简单的打印操作。由此可见,代理类可以为委托类预处调用前后都会执行一些简单的打印操作。由此可见,代理类可以为委托类预处理消息、把消息转发给委托类和事后处理消息等。理消息、把消息转发给委托类和事后处理消息等。图图a:HelloServiceProx

43、y是是HelloService的代理类的代理类 图图b:调用时序图:调用时序图动态代理类动态代理类的动态代理类的字节码在程序运行时由字节码在程序运行时由Java反射机制动态生成反射机制动态生成,无需程序员手工编,无需程序员手工编写它的源代码。动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展写它的源代码。动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为性,因为Java 反射机制可以生成任意类型的动态代理类。反射机制可以生成任意类型的动态代理类。java.lang.reflect 包中的包中的Proxy类和类和InvocationHandler 接口提供了生成动态代理类的能

44、力。接口提供了生成动态代理类的能力。Proxy类提供了创建动态代理类及其实例的静态方法类提供了创建动态代理类及其实例的静态方法:public static Class getProxyClass(ClassLoader loader, Class interfaces) throws IllegalArgumentException该静态方法负责创建动态代理类。参数该静态方法负责创建动态代理类。参数loader 指定动态代理类的类加载器,参数指定动态代理类的类加载器,参数interfaces 指定动态代理类需要实现的所有接口。指定动态代理类需要实现的所有接口。public static Obj

45、ect newProxyInstance(ClassLoader loader, Class interfaces,InvocationHandler handler) throws IllegalArgumentException该静态方法负责创建动态代理类的实例。参数该静态方法负责创建动态代理类的实例。参数loader 指定动态代理类的类加载器,指定动态代理类的类加载器,参数参数interfaces 指定动态代理类需要实现的所有接口,参数指定动态代理类需要实现的所有接口,参数handler 指定与动态代指定与动态代理类关联的理类关联的InvocationHandler 对象。对象。动态代理

46、类以下两种方式都创建了实现以下两种方式都创建了实现Foo接口的动态代理类的实例:接口的动态代理类的实例:/* 方式一方式一*/创建创建InvocationHandler对象对象InvocationHandler handler = new MyInvocationHandler(.);/创建动态代理类创建动态代理类Class proxyClass = Proxy.getProxyClass(Foo.class.getClassLoader(), new Class Foo.class );/创建动态代理类的实例创建动态代理类的实例Foo foo = (Foo) proxyClass.getCo

47、nstructor(new Class InvocationHandler.class ).newInstance(new Object handler );/* 方式二方式二*/创建创建InvocationHandler对象对象InvocationHandler handler = new MyInvocationHandler(.);/直接创建动态代理类的实例直接创建动态代理类的实例Foo foo = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(), new Class Foo.class , handler);动态代理类由由

48、Proxy类的静态方法创建的动态代理类具有以下特点:类的静态方法创建的动态代理类具有以下特点:动态代理类是动态代理类是public、final和非抽象类型的;和非抽象类型的;动态代理类继承了动态代理类继承了java.lang.reflect.Proxy类;类;动态代理类的名字以动态代理类的名字以“$Proxy”开头;开头;动态代理类实现动态代理类实现getProxyClass()和和newProxyInstance()方法中参数方法中参数interfaces指定指定的所有接口;的所有接口;Proxy 类的类的isProxyClass(Class cl)静态方法可用来判断参数指定的类是否为动静态

49、方法可用来判断参数指定的类是否为动态代理类。只有通过态代理类。只有通过Proxy类创建的类才是动态代理类;类创建的类才是动态代理类;动态代理类都具有一个动态代理类都具有一个public 类型的构造方法,该构造方法有一个类型的构造方法,该构造方法有一个InvocationHandler 类型的参数。类型的参数。InvocationHandler 接口为方法调用接口,它声明了负责调用任意一个方法的接口为方法调用接口,它声明了负责调用任意一个方法的invoke()方法:方法:Object invoke(Object proxy,Method method,Object args) throws Th

50、rowable参数参数proxy指定动态代理类实例,参数指定动态代理类实例,参数method指定被调用的方法,参数指定被调用的方法,参数args 指定向指定向被调用方法传递的参数,被调用方法传递的参数,invoke()方法的返回值表示被调用方法的返回值。方法的返回值表示被调用方法的返回值。动态代理类图图c: HelloServiceProxyFactory创建动态代理类实例创建动态代理类实例 图图d: 动态类实例调用时序图动态类实例调用时序图Lesson 15 Annotation 71目标l1、Annotation的类型l2、内建Annotation.l3、自定义Annotation(语法,

51、规则,反射应用)什么是Annotation l在已经发布的JDK1.5(tiger)中增加新的特色叫 Annotation。lAnnotation提供一种机制,将程序的元素如:类,方法,属性,参数,本地变量,包和元数据联系起来。这样编译器可以将元数据存储在Class文件中。这样虚拟机和其它对象可以根据这些元数据来决定如何使用这些程序元素或改变它们的行为。 72最简单的例子package com.yd.test;public class MyAnnotation Override public boolean equals(Object arg0) / TODO Auto-generated m

52、ethod stub return super.equals(arg0); 73作用l使用 Annotation的好處:l文档化(也就是 javaDoc 產生的說明文件可將 metadata 包進去 )l编译时检查l代码分析 74两种运行方式同时,annotation运行存在两种方式:运行时、编译时 编译时annotation在原代码编译 的时候就起作用,告诉编译器一下信息,编译器根据这个作出一定的判断.java.lang包中有三个标准annotation是编译时注解: 前面使用过的Override 指明注释的方法覆盖超类的方法Deprecated对不再使用的方法进行注释 SuppressWa

53、rnings阻止编译器的警告,例:当类型不安全时7576Annotation分类分类内建内建Annotation l内建内建Annotation Java5.0Java5.0版在版在javajava语法中经常用到的内建语法中经常用到的内建Annotation:Annotation: Deprecated定义在定义在java.lang.Deprecated中,此注释可用中,此注释可用于修辞方法、属性、类,表示不鼓励程序员使用这样的元素,于修辞方法、属性、类,表示不鼓励程序员使用这样的元素,通常是因为它很危险或存在更好的选择。在使用不被赞成的程通常是因为它很危险或存在更好的选择。在使用不被赞成的程

54、序元素或在不被赞成的代码中执行重写时,编译器会发出警告。序元素或在不被赞成的代码中执行重写时,编译器会发出警告。 Override定义在定义在java.lang.Override中,此注释只适用于修中,此注释只适用于修辞方法,表示一个方法声明打算重写超类中的另一个方法声明。辞方法,表示一个方法声明打算重写超类中的另一个方法声明。如果方法利用此注释类型进行注解但没有重写超类方法,则编如果方法利用此注释类型进行注解但没有重写超类方法,则编译器会生成一条错误消息。译器会生成一条错误消息。 SuppressWarnings用于通知用于通知java编译器禁止特定的编译警编译器禁止特定的编译警告告 pub

55、lic class UsingBuiltInAnnotation Overridepublic String toString() return ;SuppressWarnings(deprecation,unchecked)public void callDeprecatedMethod(List horseGroup) String an=abc; horseGroup.add(an); Deprecated public void deprecatedMethod() 修饰此方法覆盖了父类的方法用于通知java编译器禁止特定的编译警告 用于修饰已经过时的方法77SuppressWarni

56、ngs补充补充78小结:系统内部的Annotation2-1l1、foo类型import java.util.List;public class UsingBuiltInAnnotation /食物类食物类 class Food /干草类干草类 class Hay extends Food /动物类动物类 class Animal Food getFood() return null; /使用使用Annotation声明声明Deprecated方法方法 Deprecated void deprecatedMethod() 79小结:系统内部的Annotation2-2 /马类马类-继承动物类继

57、承动物类 class Horse extends Animal /使用使用Annotation声明覆盖方法声明覆盖方法 Override Hay getFood() return new Hay(); /使用使用Annotation声明禁止警告声明禁止警告 SuppressWarnings(deprecation,unchecked) void callDeprecatedMethod(List horseGroup) Animal an=new Animal(); an.deprecatedMethod(); horseGroup.add(an); 定义Annotation package

58、com.yd.annotation;import java.lang.annotation.*; Retention(RetentionPolicy.RUNTIME) Target(ElementType.FIELD) public interface FirstAnnotation String value(); 80说明Retention(RetentionPolicy.RUNTIME)这个meta-annotation表示我们创建的FirstAnnotation这个Annotation将会存储在Class文件中,并在java VM运行时加载它。Target(ElementType.FIE

59、LD)这个meta-annotation表示我们创建的FirstAnnotation将会为描述属性,而interface FirstAnnotation是我们自定义的Annotation,它有一个成员叫value,返回值是String。81meta-annotationl Java定义了几个标准的meta-annotation(可以用来解释annotation的annotation)l在新Package中java.lang.annotation 中包含了以下meta-annotation:82Retention说明lRetentionl1.SOURCE /按照规定使用注释,但是并不将它保留到编

60、译后的类文件中2. CLASS/将注释保留在编译后的类文件中,但是在运行时忽略它3. RUNTIME /将注释保留在编译后的类文件中,并在第一次加载类时读取它83 Target l Target l1. annotation的target是一个被标注的程序元素。target说明了annotation所修饰的对象范围:annotation可被用于packages、types(类、接口、枚举、annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数)。在annotation类型的声明中使用了target可更加明晰其修饰的目标 84ot

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论