java教學(xué)0韓建雷java反射機(jī)制release_第1頁
java教學(xué)0韓建雷java反射機(jī)制release_第2頁
java教學(xué)0韓建雷java反射機(jī)制release_第3頁
java教學(xué)0韓建雷java反射機(jī)制release_第4頁
java教學(xué)0韓建雷java反射機(jī)制release_第5頁
已閱讀5頁,還剩32頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、JAVA反射機(jī)制,議程,概述 主要功能 分析類 取得Class 對(duì)象 取得類名 找出超類 確定某類實(shí)現(xiàn)的接口 檢查接口 取得類字段 取得構(gòu)造方法 取得方法信息 取得字段的值 創(chuàng)建對(duì)象,概述,在Java運(yùn)行時(shí)環(huán)境中,對(duì)于任意一個(gè)類,能否知道這個(gè)類有哪些屬性和方法?對(duì)于任意一個(gè)對(duì)象,能否調(diào)用它的任意一個(gè)方法?答案是肯定的。這種動(dòng)態(tài)獲取類的信息以及動(dòng)態(tài)調(diào)用對(duì)象的方法的功能來自于Java 語言的反射(Reflection)機(jī)制。 Reflection是一系列的API,它用于表示或者處理當(dāng)前JVM中的類,接口和對(duì)象。,主要功能,確定一個(gè)對(duì)象的類 取出類的modifiers,數(shù)據(jù)成員,方法,構(gòu)造器和超類

2、找出某個(gè)接口里定義的常量和方法說明 創(chuàng)建一個(gè)類實(shí)例,這個(gè)實(shí)例在運(yùn)行時(shí)刻才有名字(運(yùn)行時(shí)間才生成的對(duì)象) 取得和設(shè)定對(duì)象數(shù)據(jù)成員的值,如果數(shù)據(jù)成員名是運(yùn)行時(shí)刻確定的也能做倒。 在運(yùn)行時(shí)刻調(diào)用動(dòng)態(tài)對(duì)象的方法 創(chuàng)建數(shù)組,數(shù)組大小和類型在運(yùn)行時(shí)刻才確定。也能更改數(shù)組成員的值。,分析類,如果你在編一個(gè)類瀏覽器程序,你就需要取得類在運(yùn)行時(shí)刻的有關(guān)信息。比如,你想顯示某個(gè)類的數(shù)據(jù)成員名,方法和構(gòu)造器。再比如,你想顯示某個(gè)類到底實(shí)現(xiàn)了哪些接口。這些信息可以由自省此類的Class對(duì)象來取得。 對(duì)于每個(gè)類而言,JRE都為其保留一個(gè)不變的Class類型的對(duì)象。一個(gè)Class對(duì)象包含了特定某個(gè)類的有關(guān)信息。你可以通過

3、調(diào)用Class對(duì)象的有關(guān)方法,返回特定類的構(gòu)造器對(duì)象,方法對(duì)象和數(shù)據(jù)成員對(duì)象。通過這些返回的對(duì)象,你就可以得到構(gòu)造器,方法和數(shù)據(jù)成員的所有詳細(xì)原始定義。 Class對(duì)象也包含接口信息。你可以調(diào)用Class對(duì)象的某些方法來取得某接口的modifiers,方法和公共常數(shù)。如果Class對(duì)象用來表示接口,那么Class對(duì)象的部份方法就不可用。比如getConstructors,接口根本沒構(gòu)造器,所以這個(gè)方法就沒用。,取得Class對(duì)象,如果可以取得某個(gè)類的實(shí)例,你可以調(diào)用Ojbect.getClass方法。 請(qǐng)看例子: mystery是某個(gè)類的對(duì)象。 Class c = mystery.getCla

4、ss(); 類對(duì)象c可以直接輸出,請(qǐng)看 JButton jb=new JButton(); Class mc= jb.getClass() ; System.err.println(類內(nèi)容+mc.toString() ); 如果你想取得某個(gè)類對(duì)象的超類,可以用getSuperclass方法。本例中,getSuperclass方法返回TextComponent的Class對(duì)象,因?yàn)門extComponet類是TextField的超類。 TextField t = new TextField(); Class c = t.getClass(); Class s = c.getSuperclass(

5、); 運(yùn)行后直接輸出c和s的結(jié)果是: 本類內(nèi)容class javax.swing.JTextField 超類內(nèi)容class javax.swing.text.JTextComponent,如果你知道類在編譯時(shí)的名字(類名),取出它的class對(duì)象就簡(jiǎn)單了:類名后跟“.class”后綴就行了。如: Class c1 = java.awt.Button.class; System.err.println(本類內(nèi)容+c1.toString() ); 有時(shí)候,在編譯的時(shí)候,對(duì)象屬于哪個(gè)類,類名不知道(多態(tài)性),但是在運(yùn)行的時(shí)候就知道對(duì)象屬于哪個(gè)類了(運(yùn)行時(shí)刻綁定)。這時(shí)候運(yùn)行時(shí)刻取得對(duì)象的類就應(yīng)該用f

6、orName方法。在下例中,如果字串變量strg內(nèi)容是”java.awt.Button”,那么用forName方法返回Button的Class 對(duì)象。 如:,String strg=java.awt.Button; Class c2; c2=null; try c2= Class.forName(strg) ; catch(ClassNotFoundException e) System.err.println(沒有這個(gè)類); System.exit(1); System.err.println(forName 內(nèi)容+c2.toString() );,取得類名,每個(gè)類都有類名,比如下面的類名就

7、是Point public class Point int x, y; 在運(yùn)行時(shí)刻,類名可以調(diào)用Class對(duì)象的getName方法來取得。getName返回一個(gè)字串,字串是完整的類名。 下面舉例:例子首先取得對(duì)象的Class對(duì)象,然后調(diào)用getName得到類名。,import java.lang.reflect.*; import java.awt.*; class SampleName public static void main(String args) Button b = new Button(); printName(b); static void printName(Object

8、 o) Class c = o.getClass(); String s = c.getName(); System.out.println(s); 程序輸出java.awt.Button,顯示類描述符 什么是類描述符呢?就是public, abstract, 或者final. 類描述符前面就是class關(guān)鍵字,請(qǐng)看例子: 要在運(yùn)行時(shí)刻知道類描述符得做以下兩步工作: 調(diào)用Class對(duì)象的getModifiers方法取得描述符用isPublic, isAbstract, and isFinal判斷各個(gè)描述符 請(qǐng)大家看例子。,import java.lang.reflect.*; import j

9、ava.awt.*; class SampleModifier 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.pr

10、intln(abstract); if (Modifier.isFinal(m) System.out.println(final); 從這個(gè)程序運(yùn)行結(jié)果中看到String 類是public和final的。,找出超類,java的類是有繼承結(jié)構(gòu)的,如果你想編一個(gè)類瀏覽程序,取得超類這一功能當(dāng)然需要。 用getSuperclass方法可以做到。這個(gè)方法返回超類的class對(duì)象,如果某類沒有超類就返回null.如果想找某個(gè)類的父類的父類的。那你可以反復(fù)調(diào)用getSuperclass直到返回null,import java.lang.reflect.*; import java.awt.*; clas

11、s SampleSuper public static void main(String 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

12、(className); subclass = superclass; superclass = subclass.getSuperclass(); 程序輸出如下: java.awt.Component java.lang.Object,確定某類實(shí)現(xiàn)的接口,一個(gè)對(duì)象的類型不僅僅由它的類和超類決定,還有一個(gè)重要因素是其接口。接口用implements說明,比如:public class RandomAccess DataOutput, DataInput 要知道一個(gè)類實(shí)現(xiàn)多少接口可以調(diào)用getInterface方法。此方法返回一個(gè)Class對(duì)象數(shù)組。每個(gè)元素都代表此類實(shí)現(xiàn)的一個(gè)接口。用某個(gè)元素的

13、getName方法可以取得接口的名字。 下面的程序打印出RandomAccessFile類實(shí)現(xiàn)的所有接口,import java.lang.reflect.*; import java.io.*; class SampleInterface public static void main(String args) try RandomAccessFile r = new RandomAccessFile(myfile, r); printInterfaceNames(r); catch (IOException e) System.out.println(e); static void pri

14、ntInterfaceNames(Object o) Class c = o.getClass(); Class theInterfaces = 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:

15、 java.io.DataOutput java.io.DataInput,檢查接口,對(duì)象即可以表示接口也可以表示類。如果你搞不清一個(gè)對(duì)象到底是由接口來的還是由類來的,可以用isInterface 方法來確定。 要得到接口的信息可以用Class類的方法。如果要找接口中的public常量,可以用getFields方法。用getMethods 可以取得接口中的方法。要看接口的修飾符,可以用getModifiers方法。 下面程序調(diào)用isInterface來確定Observer是一個(gè)接口,Observale是一個(gè)類。,import java.lang.reflect.*; import java.u

16、til.*; /*說明如何判斷一個(gè)對(duì)象是接口還是對(duì)象實(shí)現(xiàn)的*/ class SampleCheckInterface public static void main(String args) Class observer = Observer.class; Class observable = Observable.class; Class jb=java.awt.Button.class ; verifyInterface(observer); verifyInterface(observable); verifyInterface(jb); static void verifyInterf

17、ace(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 是類.,取得類字段,寫個(gè)程序顯示類的名字和所有方法和數(shù)據(jù)成員,調(diào)用Class對(duì)象的getFields方法就行了。這個(gè)方法返回一個(gè)字段對(duì)象(Field對(duì)象數(shù)組)數(shù)組,一個(gè)對(duì)象對(duì)應(yīng)一個(gè)字段。 如果某個(gè)公共字

18、段屬于下列情況之一,它就可以被用戶存取到 屬于本類或超類 本類實(shí)現(xiàn)的接口 本類的接口的接口。 由Field對(duì)象提供的方法允許你取得字段的名字,類型和描述符。你甚至可以給字段賦值或者取字段的值。 下面的例子打印了panel類的成員的名字和類型。注意,取成員用了getFields方法,用Field對(duì)象的getName取名字,用getType取得某個(gè)成員的Class對(duì)象,由此判斷它的 類型。,import java.lang.reflect.*; import java.awt.*; class SampleField public static void main(String args) Pan

19、el 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 typeClass = publicFieldsi.getType(); String fieldType = typeClass.ge

20、tName(); System.out.println(字段名: + fieldName +, 類型: + fieldType); ,如果一個(gè)類的字段是另一個(gè)類對(duì)象,輸出又會(huì)如何呢?請(qǐng)看SampleClassField.java import java.lang.reflect.*; public class SampleClassField public int i=0; public float f=0; public Member mb=new Member(Sam); public SampleClassField() System.err.println(start); public

21、 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.length; i+) String fieldName = publ

22、icFieldsi.getName(); Class typeClass = publicFieldsi.getType(); String fieldType = typeClass.getName(); System.out.println(字段名: +fieldName+, 類型: +fieldType); class Member private String name; public Member(String n1) name=n1; public String getMember() return name; 大家可以看到,類成員是一個(gè)對(duì)象程序也能輸出package名.類名,取得

23、構(gòu)造方法,構(gòu)造方法是在創(chuàng)建類對(duì)象時(shí)調(diào)用的特殊方法,構(gòu)造方法可以重載,由它們的參數(shù)加以區(qū)別 調(diào)用getConstructors方法可以取得類構(gòu)造方法的有關(guān)信息。這個(gè)方法返回一個(gè)數(shù)組的Constructor對(duì)象。你可以用Constructor對(duì)象里的相關(guān)方法來確定構(gòu)造方法的名字,描述符,參數(shù)類型和拋出的意外列表。你也可以用Constructor.newInstance創(chuàng)建一個(gè)新的Constructor對(duì)象 下面的例子程序打印出Rectangle類的每個(gè)構(gòu)造方法的參數(shù)表,程序是這樣執(zhí)行的。 程序用getConstructors方法取得一個(gè)數(shù)組的Constructor 對(duì)象,對(duì)于在Constructo

24、r數(shù)組的每個(gè)元素,都調(diào)用getParameterTypes方法建了一個(gè)數(shù)組的Class對(duì)象,這個(gè)數(shù)組里放了某一個(gè)構(gòu)造方法的參數(shù)類型表。程序調(diào)用getName取得每個(gè)參數(shù)的類名。,import java.lang.reflect.*; import java.awt.*; class SampleConstructor public static void main(String args) Rectangle r = new Rectangle(); showConstructors(r); static void showConstructors(Object o) Class c = o.

25、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 parameterTypes.length; k +) String parameterString = parameterTypesk.getName(); System.out.pri

26、nt(parameterString + ); System.out.println(); ,取得方法信息,如何找出類的public方法呢?當(dāng)然是調(diào)用getMethods方法。由getMethods方法返回一個(gè)數(shù)組,數(shù)組元素類型是Method對(duì)象。方法的名字,類型,參數(shù),描述和拋出的意外都可以由Method對(duì)象的方法來取得。用Method.invoke 方法自己調(diào)用這個(gè)方法。 下面的例子打印Polygon類里的公共方法的名字、返回類型,參數(shù)類型。它用getMethods方法取出方法對(duì)象數(shù)組對(duì)于Method數(shù)組的每個(gè)元素做以下事情: getName取方法名 getReturnType取返回值的類

27、型 用getParameterTypes取得返回類型的數(shù)組 對(duì)每個(gè)參數(shù)用getName取參數(shù)名。,import java.lang.reflect.*; import java.awt.*; class SampleMethod public 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

28、= 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); Class parameterTypes = theMethodsi.getParameterTypes(); System.out.print(

29、Parameter Types:); for (int k = 0; k parameterTypes.length; k +) String parameterString = parameterTypesk.getName(); System.out.print( + parameterString); System.out.println(); ,創(chuàng)建對(duì)象,如果在編譯時(shí)你不知道類名,你怎么在運(yùn)行的時(shí)候創(chuàng)建一個(gè)對(duì)象?如果你在運(yùn)行時(shí)候才知道類名,然后想新建一個(gè)對(duì)象怎么辦?比如用戶在設(shè)計(jì)器里拖了一個(gè)部件向屏幕上一放,這時(shí)候怎么辦? String className; Object o = ne

30、w (className); /這么做不對(duì)! new 操作符不能這么用。 如果你要建立一個(gè)對(duì)象,用不著構(gòu)造參數(shù),那么,你可以用Class對(duì)象的newInstance 建立之。問題是如果此類沒有無參構(gòu)造方法怎么辦呢?就扔出了NoSuchMethodException意外。構(gòu)造的信息可以從getConstructors中得到。 下面的程序先用forName找到類,然后用newInstance建立一個(gè)對(duì)象。,import java.lang.reflect.*; import java.awt.*; class SampleNoArg public static void main(String a

31、rgs) Rectangle r = (Rectangle)createObject(Rectangle); System.out.println(r.toString(); static Object createObject(String className) Object object = null; try Class classDefinition = Class.forName(className); object = classDefinition.newInstance(); catch(InstantiationException e)System.out.println(e

32、); catch(IllegalAccessException e) System.out.println(e); catch(ClassNotFoundException e) System.out.println(e); return object; ,如果構(gòu)造有參數(shù)咋辦呢?那你就用Constructor對(duì)象的newInstance方法,而不是Class對(duì)象的方法。具體按以下步驟做: 用Class對(duì)象的getConstructor方法取得Constructor對(duì)象數(shù)組。getConstructor方法帶一個(gè)參數(shù),它是一個(gè)數(shù)組,里面放的是所需要構(gòu)造方法參數(shù)的個(gè)數(shù)和類型。 用Construct

33、or的newInstance方法創(chuàng)建對(duì)象。它有一個(gè)參數(shù):一個(gè)對(duì)象數(shù)組,其元素就是要傳給構(gòu)造方法的參數(shù)表 下面的例子創(chuàng)建了兩個(gè)integer參數(shù)的一個(gè)Rectangle對(duì)象 相當(dāng)于Rectangle rectangle = new Rectangle(12, 34); 傳給newInstance的數(shù)組元素是object類型,所以呢,基本類型得包裝一下Wrapped.,import java.lang.reflect.*; import java.awt.*; class SampleInstance public static void main(String args) Rectangle r

34、ectangle; 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; try rectangleDefinition = Class.forName(java.awt.Rectangle); intArgs

35、Constructor=rectangleDefinition.getConstructor(intArgsClass); rectangle = (Rectangle) createObject(intArgsConstructor, intArgs); catch(ClassNotFoundException e)System.out.println(e); catch(NoSuchMethodException e)System.out.println(e); ,public static Object createObject(Constructor constructor,Objec

36、t arguments) System.out.println (Constructor: + constructor.toString(); Object object = null; try object = constructor.newInstance(arguments); System.out.println (Object: + object.toString(); return object; catch(InstantiationException e) System.out.println(e); catch(IllegalAccessException e) System

37、.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,取得字段的值,如果你開發(fā)debugger,運(yùn)行時(shí)候取對(duì)象字段的值當(dāng)然得會(huì)編程序。按三步走:

38、1 創(chuàng)建一個(gè)Class對(duì)象。 2 用getField方法創(chuàng)建一個(gè)Field對(duì)象 3 調(diào)用某個(gè)Field對(duì)象的的get方法 Fields類有專門的方法對(duì)付基本數(shù)據(jù)類型。比如getInt,getFloat等等,顧名思義就成了。如果是對(duì)象的話就好辦了,直接用get方法返回對(duì)象。 下面的程序取的是height字段。height是個(gè)基本數(shù)據(jù)類型int,返回的就是個(gè)對(duì)象。field是在編譯時(shí)知道名字的字段,但是,在GUI設(shè)計(jì)器等動(dòng)態(tài)的東西中,字段名在運(yùn)行時(shí)候才知道。,import java.lang.reflect.*; import java.awt.*; class SampleGet public

39、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(); try heightField = c.getField(height); heightValue = (Integer) heightField.get(r);/用getInt 也可以 System.out.println(H

40、eight: + heightValue.toString(); catch(NoSuchFieldException e) System.out.println(e); catch(SecurityException e) System.out.println(e); catch(IllegalAccessException e) System.out.println(e); ,設(shè)定字段值 一些調(diào)試器允許用戶在調(diào)試期間改變字段值。如果你在寫這樣的程序,就得照下面的步驟做: 1 先建一個(gè)Class對(duì)象 2 用getField對(duì)象的getField方法取得Field對(duì)象。 3 調(diào)用Field對(duì)象

41、的合適的set方法。 Field類提供了setBoolean,setInt等方法。如果字段是對(duì)象,直接用set方法就行了。對(duì)于原始類型對(duì)象,用wrapper也行。 下面的程序修改了width字段。,import java.lang.reflect.*; import java.awt.*; class SampleSet public static void main(String args) Rectangle r = new Rectangle(100, 20); 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.getCla

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論