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

下載本文檔

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

文檔簡介

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

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

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

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

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

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

7、是Point public class Point int x, y; 在運行時刻,類名可以調(diào)用Class對象的getName方法來取得。getName返回一個字串,字串是完整的類名。 下面舉例:例子首先取得對象的Class對象,然后調(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)鍵字,請看例子: 要在運行時刻知道類描述符得做以下兩步工作: 調(diào)用Class對象的getModifiers方法取得描述符用isPublic, isAbstract, and isFinal判斷各個描述符 請大家看例子。,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); 從這個程序運行結(jié)果中看到String 類是public和final的。,找出超類,java的類是有繼承結(jié)構(gòu)的,如果你想編一個類瀏覽程序,取得超類這一功能當(dāng)然需要。 用getSuperclass方法可以做到。這個方法返回超類的class對象,如果某類沒有超類就返回null.如果想找某個類的父類的父類的。那你可以反復(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,確定某類實現(xiàn)的接口,一個對象的類型不僅僅由它的類和超類決定,還有一個重要因素是其接口。接口用implements說明,比如:public class RandomAccess DataOutput, DataInput 要知道一個類實現(xiàn)多少接口可以調(diào)用getInterface方法。此方法返回一個Class對象數(shù)組。每個元素都代表此類實現(xiàn)的一個接口。用某個元素的

13、getName方法可以取得接口的名字。 下面的程序打印出RandomAccessFile類實現(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,檢查接口,對象即可以表示接口也可以表示類。如果你搞不清一個對象到底是由接口來的還是由類來的,可以用isInterface 方法來確定。 要得到接口的信息可以用Class類的方法。如果要找接口中的public常量,可以用getFields方法。用getMethods 可以取得接口中的方法。要看接口的修飾符,可以用getModifiers方法。 下面程序調(diào)用isInterface來確定Observer是一個接口,Observale是一個類。,import java.lang.reflect.*; import java.u

16、til.*; /*說明如何判斷一個對象是接口還是對象實現(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 是類.,取得類字段,寫個程序顯示類的名字和所有方法和數(shù)據(jù)成員,調(diào)用Class對象的getFields方法就行了。這個方法返回一個字段對象(Field對象數(shù)組)數(shù)組,一個對象對應(yīng)一個字段。 如果某個公共字

18、段屬于下列情況之一,它就可以被用戶存取到 屬于本類或超類 本類實現(xiàn)的接口 本類的接口的接口。 由Field對象提供的方法允許你取得字段的名字,類型和描述符。你甚至可以給字段賦值或者取字段的值。 下面的例子打印了panel類的成員的名字和類型。注意,取成員用了getFields方法,用Field對象的getName取名字,用getType取得某個成員的Class對象,由此判斷它的 類型。,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); ,如果一個類的字段是另一個類對象,輸出又會如何呢?請看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; 大家可以看到,類成員是一個對象程序也能輸出package名.類名,取得

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

24、r數(shù)組的每個元素,都調(diào)用getParameterTypes方法建了一個數(shù)組的Class對象,這個數(shù)組里放了某一個構(gòu)造方法的參數(shù)類型表。程序調(diào)用getName取得每個參數(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方法返回一個數(shù)組,數(shù)組元素類型是Method對象。方法的名字,類型,參數(shù),描述和拋出的意外都可以由Method對象的方法來取得。用Method.invoke 方法自己調(diào)用這個方法。 下面的例子打印Polygon類里的公共方法的名字、返回類型,參數(shù)類型。它用getMethods方法取出方法對象數(shù)組對于Method數(shù)組的每個元素做以下事情: getName取方法名 getReturnType取返回值的類

27、型 用getParameterTypes取得返回類型的數(shù)組 對每個參數(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)建對象,如果在編譯時你不知道類名,你怎么在運行的時候創(chuàng)建一個對象?如果你在運行時候才知道類名,然后想新建一個對象怎么辦?比如用戶在設(shè)計器里拖了一個部件向屏幕上一放,這時候怎么辦? String className; Object o = ne

30、w (className); /這么做不對! new 操作符不能這么用。 如果你要建立一個對象,用不著構(gòu)造參數(shù),那么,你可以用Class對象的newInstance 建立之。問題是如果此類沒有無參構(gòu)造方法怎么辦呢?就扔出了NoSuchMethodException意外。構(gòu)造的信息可以從getConstructors中得到。 下面的程序先用forName找到類,然后用newInstance建立一個對象。,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對象的newInstance方法,而不是Class對象的方法。具體按以下步驟做: 用Class對象的getConstructor方法取得Constructor對象數(shù)組。getConstructor方法帶一個參數(shù),它是一個數(shù)組,里面放的是所需要構(gòu)造方法參數(shù)的個數(shù)和類型。 用Construct

33、or的newInstance方法創(chuàng)建對象。它有一個參數(shù):一個對象數(shù)組,其元素就是要傳給構(gòu)造方法的參數(shù)表 下面的例子創(chuàng)建了兩個integer參數(shù)的一個Rectangle對象 相當(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,運行時候取對象字段的值當(dāng)然得會編程序。按三步走:

38、1 創(chuàng)建一個Class對象。 2 用getField方法創(chuàng)建一個Field對象 3 調(diào)用某個Field對象的的get方法 Fields類有專門的方法對付基本數(shù)據(jù)類型。比如getInt,getFloat等等,顧名思義就成了。如果是對象的話就好辦了,直接用get方法返回對象。 下面的程序取的是height字段。height是個基本數(shù)據(jù)類型int,返回的就是個對象。field是在編譯時知道名字的字段,但是,在GUI設(shè)計器等動態(tài)的東西中,字段名在運行時候才知道。,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 先建一個Class對象 2 用getField對象的getField方法取得Field對象。 3 調(diào)用Field對象

41、的合適的set方法。 Field類提供了setBoolean,setInt等方法。如果字段是對象,直接用set方法就行了。對于原始類型對象,用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等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論