java教学0java反射机制relea

上传人:夏** 文档编号:587556057 上传时间:2024-09-06 格式:PPT 页数:37 大小:128.50KB
返回 下载 相关 举报
java教学0java反射机制relea_第1页
第1页 / 共37页
java教学0java反射机制relea_第2页
第2页 / 共37页
java教学0java反射机制relea_第3页
第3页 / 共37页
java教学0java反射机制relea_第4页
第4页 / 共37页
java教学0java反射机制relea_第5页
第5页 / 共37页
点击查看更多>>
资源描述

《java教学0java反射机制relea》由会员分享,可在线阅读,更多相关《java教学0java反射机制relea(37页珍藏版)》请在金锄头文库上搜索。

1、JAVAJAVA反射机制反射机制整理课件议程议程概述概述主要功能主要功能分析类分析类取得取得Class Class 对象对象取得类名取得类名找出超类找出超类确定某类实现的接口确定某类实现的接口检查接口检查接口取得类字段取得类字段取得构造方法取得构造方法取得方法信息取得方法信息取得字段的值取得字段的值创建对象创建对象整理课件概述概述在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法?答案是肯定的。这种动态获取类的信息以及动态调用对象的方法的功能来自于Java 语言的反射(Reflection)机制。Reflection是一系列的AP

2、I,它用于表示或者处理当前JVM中的类,接口和对象。整理课件主要功能主要功能确定一个对象的类取出类的modifiers,数据成员,方法,构造器和超类找出某个接口里定义的常量和方法说明创建一个类实例,这个实例在运行时刻才有名字(运行时间才生成的对象)取得和设定对象数据成员的值,如果数据成员名是运行时刻确定的也能做倒。在运行时刻调用动态对象的方法创建数组,数组大小和类型在运行时刻才确定。也能更改数组成员的值。整理课件分析类分析类如果你在编一个类浏览器程序,你就需要取得类在运行时刻的有关信息。比如,你想显示某个类的数据成员名,方法和构造器。再比如,你想显示某个类到底实现了哪些接口。这些信息可以由自省

3、此类的Class对象来取得。对于每个类而言,JRE都为其保留一个不变的Class类型的对象。一个Class对象包含了特定某个类的有关信息。你可以通过调用Class对象的有关方法,返回特定类的构造器对象,方法对象和数据成员对象。通过这些返回的对象,你就可以得到构造器,方法和数据成员的所有详细原始定义。Class对象也包含接口信息。你可以调用Class对象的某些方法来取得某接口的modifiers,方法和公共常数。如果Class对象用来表示接口,那么Class对象的部份方法就不可用。比如getConstructors,接口根本没构造器,所以这个方法就没用。整理课件取得取得ClassClass对象对

4、象如果可以取得某个类的实例,你可以调用方法。 请看例子:mystery是某个类的对象。Class c = mystery.getClass();类对象c可以直接输出,请看 JButton jb=new JButton(); Class mc= jb.getClass() ; System.err.println(类内容+mc.toString() );如果你想取得某个类对象的超类,可以用getSuperclass方法。本例中,getSuperclass方法返回TextComponent的Class对象,因为TextComponet类是TextField的超类。TextField t = new

5、 TextField();Class c = t.getClass();Class s = c.getSuperclass();运行后直接输出c和s的结果是:本类内容超类内容整理课件如果你知道类在编译时的名字(类名),取出它的class对象就简单了:类名后跟“.class”后缀就行了。如:Class c1 = java.awt.Button.class;System.err.println(本类内容+c1.toString() );有时候,在编译的时候,对象属于哪个类,类名不知道(多态性),但是在运行的时候就知道对象属于哪个类了(运行时刻绑定)。这时候运行时刻取得对象的类就应该用forName

6、方法。在下例中,如果字串变量strg内容是”java.awt.Button”,那么用forName方法返回Button的Class 对象。如:整理课件String strg=java.awt.Button;Class c2;c2=null;tryc2= Class.forName(strg) ;catch(ClassNotFoundException e)System.err.println(没有这个类);System.exit(1);System.err.println(forName 内容+c2.toString() );整理课件取得类名取得类名每个类都有类名,比如下面的类名就是Point

7、public class Point int x, y;在运行时刻,类名可以调用Class对象的getName方法来取得。getName返回一个字串,字串是完整的类名。下面举例:例子首先取得对象的Class对象,然后调用getName得到类名。整理课件import java.lang.reflect.*;import java.awt.*;class SampleNamepublic static void main(String args)Button b = new Button();printName(b);static void printName(Object o)Class c =

8、 o.getClass();String s = c.getName();System.out.println(s);程序输出整理课件显示类描述符什么是类描述符呢?就是public, abstract, 或者final. 类描述符前面就是class关键字,请看例子:要在运行时刻知道类描述符得做以下两步工作:调用Class对象的getModifiers方法取得描述符用isPublic, isAbstract, and isFinal判断各个描述符请大家看例子。整理课件import java.lang.reflect.*;import java.awt.*;class SampleModifier

9、public static void main(String args)String s = new String();printModifiers(s);public static void printModifiers(Object o)Class c = o.getClass();int m = c.getModifiers();if (Modifier.isPublic(m)System.out.println(public);if (Modifier.isAbstract(m)System.out.println(abstract);if (Modifier.isFinal(m)Sy

10、stem.out.println(final);从这个程序运行结果中看到String 类是public和final的。整理课件找出超类找出超类java的类是有继承结构的,如果你想编一个类浏览程序,取得超类这一功能当然需要。用getSuperclass方法可以做到。这个方法返回超类的class对象,如果某类没有超类就返回null.如果想找某个类的父类的父类的。那你可以反复调用getSuperclass直到返回null整理课件import java.lang.reflect.*;import java.awt.*;class SampleSuperpublic static void main(S

11、tring args)Button b = new Button();printSuperclasses(b);static void printSuperclasses(Object o)Class subclass = o.getClass();Class superclass = subclass.getSuperclass();while (superclass != null)String className = superclass.getName();System.out.println(className);subclass = superclass;superclass =

12、subclass.getSuperclass();程序输出如下整理课件确定某类实现的接口确定某类实现的接口一个对象的类型不仅仅由它的类和超类决定,还有一个重要因素是其接口。接口用implements说明,比如:public class RandomAccessFile implements DataOutput, DataInput要知道一个类实现多少接口可以调用getInterface方法。此方法返回一个Class对象数组。每个元素都代表此类实现的一个接口。用某个元素的getName方法可以取得接口的名字。下面的程序打印出RandomAccessFile类实现的所有接口整理课件import

13、java.lang.reflect.*;import java.io.*;class SampleInterfacepublic static void main(String args)tryRandomAccessFile r = new RandomAccessFile(myfile, r);printInterfaceNames(r);catch (IOException e)System.out.println(e);static void printInterfaceNames(Object o)Class c = o.getClass();Class theInterfaces

14、= c.getInterfaces();for (int i = 0; i theInterfaces.length; i+)String interfaceName = theInterfacesi.getName();System.out.println(interfaceName);Note that the interface names printed by the sample program are fully qualified:整理课件检查接口检查接口对象即可以表示接口也可以表示类。如果你搞不清一个对象到底是由接口来的还是由类来的,可以用isInterface 方法来确定。要

15、得到接口的信息可以用Class类的方法。如果要找接口中的public常量,可以用getFields方法。用getMethods 可以取得接口中的方法。要看接口的修饰符,可以用getModifiers方法。下面程序调用isInterface来确定Observer是一个接口,Observale是一个类。整理课件import java.lang.reflect.*;import java.util.*;/*说明如何判断一个对象是接口还是对象实现的*/class SampleCheckInterfacepublic static void main(String args)Class observer

16、 = Observer.class;Class observable = Observable.class;Class jb=java.awt.Button.class ;verifyInterface(observer);verifyInterface(observable);verifyInterface(jb);static void verifyInterface(Class c)String name = c.getName();if (c.isInterface()System.out.println(name + 是接口.); else System.out.println(na

17、me + 是类.);程序的输出是是接口.java.util.Observable 是类.java.awt.Button 是类.整理课件取得类字段写个程序显示类的名字和所有方法和数据成员,调用Class对象的getFields方法就行了。这个方法返回一个字段对象(Field对象数组)数组,一个对象对应一个字段。如果某个公共字段属于下列情况之一,它就可以被用户存取到u属于本类或超类u本类实现的接口u本类的接口的接口。由Field对象提供的方法允许你取得字段的名字,类型和描述符。你甚至可以给字段赋值或者取字段的值。下面的例子打印了panel类的成员的名字和类型。注意,取成员用了getFields方法

18、,用Field对象的getName取名字,用getType取得某个成员的Class对象,由此判断它的类型。整理课件import java.lang.reflect.*;import java.awt.*;class SampleFieldpublic static void main(String args)Panel g = new Panel ();printFieldNames(g);static void printFieldNames(Object o)Class c = o.getClass();Field publicFields = c.getFields();for (int

19、 i = 0; i publicFields.length; i+)String fieldName = publicFieldsi.getName();Class typeClass = publicFieldsi.getType();String fieldType = typeClass.getName();System.out.println(字段名: + fieldName +, 类型: + fieldType);整理课件如果一个类的字段是另一个类对象,输出又会如何呢?请看import java.lang.reflect.*;public class SampleClassField

20、public int i=0; public float f=0;public Member mb=new Member(Sam);public SampleClassField()System.err.println(start);public static void main(String args)SampleClassField sampleClassField1 = new SampleClassField();printFieldNames(sampleClassField1) ;public static void printFieldNames(Object o)Class c

21、 = o.getClass();Field publicFields = c.getFields();for (int i = 0; i publicFields.length; i+)String fieldName = publicFieldsi.getName();Class typeClass = publicFieldsi.getType();String fieldType = typeClass.getName();System.out.println(字段名: +fieldName+, 类型: +fieldType);class Memberprivate String nam

22、e;public Member(String n1) name=n1; public String getMember() return name;大家可以看到,类成员是一个对象程序也能输出package名.类名整理课件取得构造方法取得构造方法构造方法是在创建类对象时调用的特殊方法,构造方法可以重载,由它们的参数加以区别调用getConstructors方法可以取得类构造方法的有关信息。这个方法返回一个数组的Constructor对象。你可以用Constructor对象里的相关方法来确定构造方法的名字,描述符,参数类型和抛出的意外列表。你也可以用创建一个新的Constructor对象下面的例子

23、程序打印出Rectangle类的每个构造方法的参数表,程序是这样执行的。程序用getConstructors方法取得一个数组的Constructor 对象,对于在Constructor数组的每个元素,都调用getParameterTypes方法建了一个数组的Class对象,这个数组里放了某一个构造方法的参数类型表。程序调用getName取得每个参数的类名。整理课件import java.lang.reflect.*;import java.awt.*;class SampleConstructorpublic static void main(String args)Rectangle r =

24、 new Rectangle();showConstructors(r);static void showConstructors(Object o)Class c = o.getClass();Constructor theConstructors = c.getConstructors();for (int i = 0; i theConstructors.length; i+)System.out.print( );Class parameterTypes=theConstructorsi.getParameterTypes();for (int k = 0;k parameterTyp

25、es.length; k +)String parameterString = parameterTypesk.getName();System.out.print(parameterString + );System.out.println();整理课件取得方法信息取得方法信息如何找出类的public方法呢?当然是调用getMethods方法。由getMethods方法返回一个数组,数组元素类型是Method对象。方法的名字,类型,参数,描述和抛出的意外都可以由Method对象的方法来取得。用Method.invoke 方法自己调用这个方法。下面的例子打印Polygon类里的公共方法的名字、

26、返回类型,参数类型。它用getMethods方法取出方法对象数组对于Method数组的每个元素做以下事情:ugetName取方法名ugetReturnType取返回值的类型u用getParameterTypes取得返回类型的数组u对每个参数用getName取参数名。整理课件import java.lang.reflect.*;import java.awt.*;class SampleMethodpublic static void main(String args)Polygon p = new Polygon();showMethods(p);static void showMethods

27、(Object o)Class c = o.getClass();Method theMethods = c.getMethods();for (int i = 0; i theMethods.length; i+)String methodString = theMethodsi.getName();System.out.println(Name: + methodString);String returnString=theMethodsi.getReturnType().getName();System.out.println( Return Type: + returnString);

28、Class parameterTypes = theMethodsi.getParameterTypes();System.out.print( Parameter Types:);for (int k = 0; k parameterTypes.length; k +)String parameterString = parameterTypesk.getName();System.out.print( + parameterString);System.out.println();整理课件创建对象创建对象如果在编译时你不知道类名,你怎么在运行的时候创建一个对象?如果你在运行时候才知道类名,

29、然后想新建一个对象怎么办?比如用户在设计器里拖了一个部件向屏幕上一放,这时候怎么办?String className;Object o = new (className); /这么做不对!new 操作符不能这么用。如果你要建立一个对象,用不着构造参数,那么,你可以用Class对象的newInstance 建立之。问题是如果此类没有无参构造方法怎么办呢?就扔出了NoSuchMethodException意外。构造的信息可以从getConstructors中得到。 下面的程序先用forName找到类,然后用newInstance建立一个对象。整理课件import java.lang.reflect

30、.*;import java.awt.*;class SampleNoArgpublic static void main(String args)Rectangle r = (Rectangle)createObject(Rectangle);System.out.println(r.toString();static Object createObject(String className)Object object = null;tryClass classDefinition = Class.forName(className);object = classDefinition.new

31、Instance();catch(InstantiationException e)System.out.println(e);catch(IllegalAccessException e) System.out.println(e); catch(ClassNotFoundException e) System.out.println(e); return object;整理课件如果构造有参数咋办呢?那你就用Constructor对象的newInstance方法,而不是Class对象的方法。具体按以下步骤做:用Class对象的getConstructor方法取得Constructor对象数组

32、。getConstructor方法带一个参数,它是一个数组,里面放的是所需要构造方法参数的个数和类型。用Constructor的newInstance方法创建对象。它有一个参数:一个对象数组,其元素就是要传给构造方法的参数表下面的例子创建了两个integer参数的一个Rectangle对象相当于Rectangle rectangle = new Rectangle(12, 34);传给newInstance的数组元素是object类型,所以呢,基本类型得包装一下Wrapped.整理课件import java.lang.reflect.*;import java.awt.*;class Samp

33、leInstancepublic static void main(String args)Rectangle rectangle;Class rectangleDefinition;Class intArgsClass = new Class int.class, int.class;Integer height = new Integer(12);Integer width = new Integer(34);Object intArgs = new Object height, width;Constructor intArgsConstructor;tryrectangleDefini

34、tion = Class.forName(java.awt.Rectangle);intArgsConstructor=rectangleDefinition.getConstructor(intArgsClass);rectangle = (Rectangle) createObject(intArgsConstructor, intArgs);catch(ClassNotFoundException e)System.out.println(e);catch(NoSuchMethodException e)System.out.println(e); 整理课件public static O

35、bject createObject(Constructor constructor,Object arguments)System.out.println (Constructor: + constructor.toString();Object object = null;tryobject = constructor.newInstance(arguments);System.out.println (Object: + object.toString();return object;catch(InstantiationException e) System.out.println(e

36、); catch(IllegalAccessException e) System.out.println(e); catch(IllegalArgumentException e) System.out.println(e); catch(InvocationTargetException e) System.out.println(e); return object;程序输出:Constructor: public java.awt.Rectangle(int,int)Object: java.awt.Rectanglex=0,y=0,width=12,height=34整理课件取得字段的

37、值取得字段的值如果你开发debugger,运行时候取对象字段的值当然得会编程序。按三步走:1 创建一个Class对象。2 用getField方法创建一个Field对象3 调用某个Field对象的的get方法Fields类有专门的方法对付基本数据类型。比如getInt,getFloat等等,顾名思义就成了。如果是对象的话就好办了,直接用get方法返回对象。下面的程序取的是height字段。height是个基本数据类型int,返回的就是个wapper对象。field是在编译时知道名字的字段,但是,在GUI设计器等动态的东西中,字段名在运行时候才知道。整理课件import java.lang.ref

38、lect.*;import java.awt.*;class SampleGetpublic static void main(String args)Rectangle r = new Rectangle(100, 325);printHeight(r);static void printHeight(Rectangle r)Field heightField;Integer heightValue;Class c = r.getClass();tryheightField = c.getField(height);heightValue = (Integer) heightField.ge

39、t(r);/用getInt 也可以System.out.println(Height: + heightValue.toString();catch(NoSuchFieldException e) System.out.println(e); catch(SecurityException e) System.out.println(e); catch(IllegalAccessException e) System.out.println(e);整理课件设定字段值一些调试器允许用户在调试期间改变字段值。如果你在写这样的程序,就得照下面的步骤做:1 先建一个Class对象2 用getField

40、对象的getField方法取得Field对象。3 调用Field对象的合适的set方法。Field类提供了setBoolean,setInt等方法。如果字段是对象,直接用set方法就行了。对于原始类型对象,用wrapper也行。下面的程序修改了width字段。整理课件import java.lang.reflect.*;import java.awt.*;class SampleSetpublic static void main(String args)Rectangle r = new Rectangle(100, 20);System.out.println(original: + r.

41、toString();modifyWidth(r, new Integer(300);System.out.println(modified: + r.toString();static void modifyWidth(Rectangle r, Integer widthParam )Field widthField;Integer widthValue;Class c = r.getClass();trywidthField = c.getField(width);widthField.set(r, widthParam);catch(NoSuchFieldException e) Sys

42、tem.out.println(e); catch(IllegalAccessException e) System.out.println(e); original: java.awt.Rectanglex=0,y=0,width=100,height=20modified: java.awt.Rectanglex=0,y=0,width=300,height=20整理课件调用方法调用方法jbuilder的调试器在运行时候可以让用户调用方法。你怎么知道用户在运行时会调用什么方法呢?所以在你写代码的时候也没办法直接调用方法。1 创建一个Class对象。2 用getMethod方法取得一个Met

43、hod对象。getMethod方法有两个参数:一个串是方法名,别一个是Class对象数组. 数组每个元素都是方法的参数。3 用Method对象的invoke方法调用之。它一样有两个参数:一个是对象数组,里面放参数表;另一个是此方法存在的对象。下面的程序动态调用方法。整理课件import java.lang.reflect.*;class SampleInvokepublic static void main(String args)String firstWord = Hello ;String secondWord = everybody.;String bothWords = append

44、(firstWord, secondWord);System.out.println(bothWords);public static String append(String firstWord, String secondWord)String result = null;Class c = String.class;Class parameterTypes = new Class String.class;Method concatMethod;Object arguments = new Object secondWord;tryconcatMethod = c.getMethod(c

45、oncat, parameterTypes);result = (String) concatMethod.invoke(firstWord, arguments);catch(NoSuchMethodException e) System.out.println(e); catch(IllegalAccessException e) System.out.println(e); catch(InvocationTargetException e) System.out.println(e); return result;程序输出Hello everybody.整理课件小结小结概述概述主要功能主要功能分析类分析类取得取得ClassClass对象对象取得类名取得类名找出超类找出超类确定某类实现的接口确定某类实现的接口检查接口检查接口取得类字段取得类字段取得构造方法取得构造方法取得方法信息取得方法信息取得字段的值取得字段的值创建对象创建对象整理课件

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 医学/心理学 > 基础医学

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号