java教学0韩建雷 java反射机制release.ppt

上传人:sccc 文档编号:6205736 上传时间:2023-10-05 格式:PPT 页数:37 大小:317.02KB
返回 下载 相关 举报
java教学0韩建雷 java反射机制release.ppt_第1页
第1页 / 共37页
java教学0韩建雷 java反射机制release.ppt_第2页
第2页 / 共37页
java教学0韩建雷 java反射机制release.ppt_第3页
第3页 / 共37页
java教学0韩建雷 java反射机制release.ppt_第4页
第4页 / 共37页
java教学0韩建雷 java反射机制release.ppt_第5页
第5页 / 共37页
点击查看更多>>
资源描述

《java教学0韩建雷 java反射机制release.ppt》由会员分享,可在线阅读,更多相关《java教学0韩建雷 java反射机制release.ppt(37页珍藏版)》请在三一办公上搜索。

1、JAVA反射机制,议程,概述主要功能分析类取得Class 对象取得类名找出超类确定某类实现的接口检查接口取得类字段取得构造方法取得方法信息取得字段的值创建对象,概述,在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法?答案是肯定的。这种动态获取类的信息以及动态调用对象的方法的功能来自于Java 语言的反射(Reflection)机制。Reflection是一系列的API,它用于表示或者处理当前JVM中的类,接口和对象。,主要功能,确定一个对象的类取出类的modifiers,数据成员,方法,构造器和超类找出某个接口里定义的常量和方法

2、说明创建一个类实例,这个实例在运行时刻才有名字(运行时间才生成的对象)取得和设定对象数据成员的值,如果数据成员名是运行时刻确定的也能做倒。在运行时刻调用动态对象的方法创建数组,数组大小和类型在运行时刻才确定。也能更改数组成员的值。,分析类,如果你在编一个类浏览器程序,你就需要取得类在运行时刻的有关信息。比如,你想显示某个类的数据成员名,方法和构造器。再比如,你想显示某个类到底实现了哪些接口。这些信息可以由自省此类的Class对象来取得。对于每个类而言,JRE都为其保留一个不变的Class类型的对象。一个Class对象包含了特定某个类的有关信息。你可以通过调用Class对象的有关方法,返回特定类

3、的构造器对象,方法对象和数据成员对象。通过这些返回的对象,你就可以得到构造器,方法和数据成员的所有详细原始定义。Class对象也包含接口信息。你可以调用Class对象的某些方法来取得某接口的modifiers,方法和公共常数。如果Class对象用来表示接口,那么Class对象的部份方法就不可用。比如getConstructors,接口根本没构造器,所以这个方法就没用。,取得Class对象,如果可以取得某个类的实例,你可以调用Ojbect.getClass方法。请看例子:mystery是某个类的对象。Class c=mystery.getClass();类对象c可以直接输出,请看 JButton

4、 jb=new JButton();Class mc=jb.getClass();System.err.println(类内容+mc.toString();如果你想取得某个类对象的超类,可以用getSuperclass方法。本例中,getSuperclass方法返回TextComponent的Class对象,因为TextComponet类是TextField的超类。TextField t=new TextField();Class c=t.getClass();Class s=c.getSuperclass();运行后直接输出c和s的结果是:本类内容class javax.swing.JTex

5、tField超类内容class javax.swing.text.JTextComponent,如果你知道类在编译时的名字(类名),取出它的class对象就简单了:类名后跟“.class”后缀就行了。如:Class c1=java.awt.Button.class;System.err.println(本类内容+c1.toString();有时候,在编译的时候,对象属于哪个类,类名不知道(多态性),但是在运行的时候就知道对象属于哪个类了(运行时刻绑定)。这时候运行时刻取得对象的类就应该用forName方法。在下例中,如果字串变量strg内容是”java.awt.Button”,那么用forNa

6、me方法返回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();,取得类名,每个类都有类名,比如下面的类名就是Pointpublic class Point int x,y;在运行时刻,类名可以调用Class对象的getName方法来取得。

7、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=o.getClass();String s=c.getName();System.out.println(s);程序输出java.aw

8、t.Button,显示类描述符什么是类描述符呢?就是public,abstract,或者final.类描述符前面就是class关键字,请看例子:要在运行时刻知道类描述符得做以下两步工作:调用Class对象的getModifiers方法取得描述符用isPublic,isAbstract,and isFinal判断各个描述符请大家看例子。,import java.lang.reflect.*;import java.awt.*;class SampleModifierpublic static void main(String args)String s=new String();printMod

9、ifiers(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)System.out.println(final);从这个程序运行结果中看到String 类是public和final的。,找出超类,java的类是有继承

10、结构的,如果你想编一个类浏览程序,取得超类这一功能当然需要。用getSuperclass方法可以做到。这个方法返回超类的class对象,如果某类没有超类就返回null.如果想找某个类的父类的父类的。那你可以反复调用getSuperclass直到返回null,import java.lang.reflect.*;import java.awt.*;class SampleSuperpublic static void main(String args)Button b=new Button();printSuperclasses(b);static void printSuperclasses(

11、Object o)Class subclass=o.getClass();Class superclass=subclass.getSuperclass();while(superclass!=null)String className=superclass.getName();System.out.println(className);subclass=superclass;superclass=subclass.getSuperclass();程序输出如下:java.awt.Component java.lang.Object,确定某类实现的接口,一个对象的类型不仅仅由它的类和超类决定,还

12、有一个重要因素是其接口。接口用implements说明,比如:public class RandomAccessFile implements DataOutput,DataInput要知道一个类实现多少接口可以调用getInterface方法。此方法返回一个Class对象数组。每个元素都代表此类实现的一个接口。用某个元素的getName方法可以取得接口的名字。下面的程序打印出RandomAccessFile类实现的所有接口,import java.lang.reflect.*;import java.io.*;class SampleInterfacepublic static void m

13、ain(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=c.getInterfaces();for(int i=0;i theInterfaces.length;i+)String interfaceName=theInte

14、rfacesi.getName();System.out.println(interfaceName);Note that the interface names printed by the sample program are fully qualified:java.io.DataOutput java.io.DataInput,检查接口,对象即可以表示接口也可以表示类。如果你搞不清一个对象到底是由接口来的还是由类来的,可以用isInterface 方法来确定。要得到接口的信息可以用Class类的方法。如果要找接口中的public常量,可以用getFields方法。用getMethods

15、 可以取得接口中的方法。要看接口的修饰符,可以用getModifiers方法。下面程序调用isInterface来确定Observer是一个接口,Observale是一个类。,import java.lang.reflect.*;import java.util.*;/*说明如何判断一个对象是接口还是对象实现的*/class SampleCheckInterfacepublic static void main(String args)Class observer=Observer.class;Class observable=Observable.class;Class jb=java.aw

16、t.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(name+是类.);程序的输出是java.util.Observer是接口.java.util.Observable 是类.java.awt.Button 是

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

18、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 i=0;i publicFields.length;i+)String fieldName=publicFieldsi.getName();Class

19、typeClass=publicFieldsi.getType();String fieldType=typeClass.getName();System.out.println(字段名:+fieldName+,类型:+fieldType);,如果一个类的字段是另一个类对象,输出又会如何呢?请看SampleClassField.javaimport java.lang.reflect.*;public class SampleClassFieldpublic int i=0;public float f=0;public Member mb=new Member(Sam);public Sam

20、pleClassField()System.err.println(start);public static void main(String args)SampleClassField sampleClassField1=new SampleClassField();printFieldNames(sampleClassField1);public static void printFieldNames(Object o)Class c=o.getClass();Field publicFields=c.getFields();for(int i=0;i publicFields.lengt

21、h;i+)String fieldName=publicFieldsi.getName();Class typeClass=publicFieldsi.getType();String fieldType=typeClass.getName();System.out.println(字段名:+fieldName+,类型:+fieldType);class Memberprivate String name;public Member(String n1)name=n1;public String getMember()return name;大家可以看到,类成员是一个对象程序也能输出packa

22、ge名.类名,取得构造方法,构造方法是在创建类对象时调用的特殊方法,构造方法可以重载,由它们的参数加以区别调用getConstructors方法可以取得类构造方法的有关信息。这个方法返回一个数组的Constructor对象。你可以用Constructor对象里的相关方法来确定构造方法的名字,描述符,参数类型和抛出的意外列表。你也可以用Constructor.newInstance创建一个新的Constructor对象下面的例子程序打印出Rectangle类的每个构造方法的参数表,程序是这样执行的。程序用getConstructors方法取得一个数组的Constructor 对象,对于在Cons

23、tructor数组的每个元素,都调用getParameterTypes方法建了一个数组的Class对象,这个数组里放了某一个构造方法的参数类型表。程序调用getName取得每个参数的类名。,import java.lang.reflect.*;import java.awt.*;class SampleConstructorpublic static void main(String args)Rectangle r=new Rectangle();showConstructors(r);static void showConstructors(Object o)Class c=o.getCl

24、ass();Constructor theConstructors=c.getConstructors();for(int i=0;i theConstructors.length;i+)System.out.print();Class parameterTypes=theConstructorsi.getParameterTypes();for(int k=0;k parameterTypes.length;k+)String parameterString=parameterTypesk.getName();System.out.print(parameterString+);System

25、.out.println();,取得方法信息,如何找出类的public方法呢?当然是调用getMethods方法。由getMethods方法返回一个数组,数组元素类型是Method对象。方法的名字,类型,参数,描述和抛出的意外都可以由Method对象的方法来取得。用Method.invoke 方法自己调用这个方法。下面的例子打印Polygon类里的公共方法的名字、返回类型,参数类型。它用getMethods方法取出方法对象数组对于Method数组的每个元素做以下事情:getName取方法名getReturnType取返回值的类型用getParameterTypes取得返回类型的数组对每个参数用

26、getName取参数名。,import java.lang.reflect.*;import java.awt.*;class SampleMethodpublic static void main(String args)Polygon p=new Polygon();showMethods(p);static void showMethods(Object o)Class c=o.getClass();Method theMethods=c.getMethods();for(int i=0;i theMethods.length;i+)String methodString=theMeth

27、odsi.getName();System.out.println(Name:+methodString);String returnString=theMethodsi.getReturnType().getName();System.out.println(Return Type:+returnString);Class parameterTypes=theMethodsi.getParameterTypes();System.out.print(Parameter Types:);for(int k=0;k parameterTypes.length;k+)String paramete

28、rString=parameterTypesk.getName();System.out.print(+parameterString);System.out.println();,创建对象,如果在编译时你不知道类名,你怎么在运行的时候创建一个对象?如果你在运行时候才知道类名,然后想新建一个对象怎么办?比如用户在设计器里拖了一个部件向屏幕上一放,这时候怎么办?String className;Object o=new(className);/这么做不对!new 操作符不能这么用。如果你要建立一个对象,用不着构造参数,那么,你可以用Class对象的newInstance 建立之。问题是如果此类没

29、有无参构造方法怎么办呢?就扔出了NoSuchMethodException意外。构造的信息可以从getConstructors中得到。下面的程序先用forName找到类,然后用newInstance建立一个对象。,import java.lang.reflect.*;import java.awt.*;class SampleNoArgpublic static void main(String args)Rectangle r=(Rectangle)createObject(Rectangle);System.out.println(r.toString();static Object cr

30、eateObject(String className)Object object=null;tryClass classDefinition=Class.forName(className);object=classDefinition.newInstance();catch(InstantiationException e)System.out.println(e);catch(IllegalAccessException e)System.out.println(e);catch(ClassNotFoundException e)System.out.println(e);return

31、object;,如果构造有参数咋办呢?那你就用Constructor对象的newInstance方法,而不是Class对象的方法。具体按以下步骤做:用Class对象的getConstructor方法取得Constructor对象数组。getConstructor方法带一个参数,它是一个数组,里面放的是所需要构造方法参数的个数和类型。用Constructor的newInstance方法创建对象。它有一个参数:一个对象数组,其元素就是要传给构造方法的参数表下面的例子创建了两个integer参数的一个Rectangle对象相当于Rectangle rectangle=new Rectangle(12

32、,34);传给newInstance的数组元素是object类型,所以呢,基本类型得包装一下Wrapped.,import java.lang.reflect.*;import java.awt.*;class SampleInstancepublic 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

33、Integer(34);Object intArgs=new Object height,width;Constructor intArgsConstructor;tryrectangleDefinition=Class.forName(java.awt.Rectangle);intArgsConstructor=rectangleDefinition.getConstructor(intArgsClass);rectangle=(Rectangle)createObject(intArgsConstructor,intArgs);catch(ClassNotFoundException e)

34、System.out.println(e);catch(NoSuchMethodException e)System.out.println(e);,public static Object createObject(Constructor constructor,Object arguments)System.out.println(Constructor:+constructor.toString();Object object=null;tryobject=constructor.newInstance(arguments);System.out.println(Object:+obje

35、ct.toString();return object;catch(InstantiationException e)System.out.println(e);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.Rectangl

36、e(int,int)Object:java.awt.Rectanglex=0,y=0,width=12,height=34,取得字段的值,如果你开发debugger,运行时候取对象字段的值当然得会编程序。按三步走:1 创建一个Class对象。2 用getField方法创建一个Field对象3 调用某个Field对象的的get方法Fields类有专门的方法对付基本数据类型。比如getInt,getFloat等等,顾名思义就成了。如果是对象的话就好办了,直接用get方法返回对象。下面的程序取的是height字段。height是个基本数据类型int,返回的就是个wapper对象。field是在编译时

37、知道名字的字段,但是,在GUI设计器等动态的东西中,字段名在运行时候才知道。,import java.lang.reflect.*;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.get

38、Field(height);heightValue=(Integer)heightField.get(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);,设定字段值一些调试器允许用户在调试期间改变字段值。如果你在写这

39、样的程序,就得照下面的步骤做:1 先建一个Class对象2 用getField对象的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);

40、System.out.println(original:+r.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(NoSuch

41、FieldException e)System.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

42、方法取得一个Method对象。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(f

43、irstWord,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(concat,paramete

44、rTypes);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.,小结,概述主要功能分析类取得Class对象取得类名找出超类确定某类实现的接口检查接口取得类字段取得构造方法取得方法信息取得字段的值创建对象,

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 建筑/施工/环境 > 农业报告


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号