Java反射機(jī)制詳解_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
Java 反射機(jī)制介紹
Java 反射機(jī)制。通俗來(lái)講呢,就是在運(yùn)行狀態(tài)中,我們可以根據(jù)“類(lèi)的部分已經(jīng)的信息”來(lái)還原“類(lèi)的全部的信息”。這里“類(lèi)的部分已經(jīng)的信息”,可以是“類(lèi)名”或“類(lèi)的對(duì)象”等信息。“類(lèi)的全部信息”就是指“類(lèi)的屬性,方法,繼承關(guān)系和Annotation注解”等內(nèi)容。
舉個(gè)簡(jiǎn)單的例子:假設(shè)對(duì)于類(lèi)ReflectionTest.java,我們知道的唯一信息是它的類(lèi)名是“com.bjpowernode.Reflection”。這時(shí),我們想要知道ReflectionTest.java的其它信息(比如它的構(gòu)造函數(shù),它的成員變量等等),要怎么辦呢?
這就需要用到“反射”。通過(guò)反射,我們可以解析出ReflectionTest.java的完整信息,包括它的構(gòu)造函數(shù),成員變量,繼承關(guān)系等等。
在了解了“java 反射機(jī)制”的概念之后,接下來(lái)思考一個(gè)問(wèn)題:如何根據(jù)類(lèi)的類(lèi)名,來(lái)獲取類(lèi)的完整信息呢?
這個(gè)過(guò)程主要分為兩步:
第1步:根據(jù)“類(lèi)名”來(lái)獲取對(duì)應(yīng)類(lèi)的Class對(duì)象。
第2步:通過(guò)Class對(duì)象的函數(shù)接口,來(lái)讀取“類(lèi)的構(gòu)造函數(shù),成員變量”等信息。
下面,我們根據(jù)示例來(lái)加深對(duì)這個(gè)概念的理解。示例如下(Demo1.java):
package com.bjpowernode.test; import java.lang.Class; public class Demo1 { public static void main(String[] args) { try { // 根據(jù)“類(lèi)名”獲取 對(duì)應(yīng)的Class對(duì)象 Class<?> cls = Class.forName("com.bjpowernode.test.Person"); // 新建對(duì)象。newInstance()會(huì)調(diào)用類(lèi)不帶參數(shù)的構(gòu)造函數(shù) Object obj = cls.newInstance(); System.out.println("cls="+cls); } catch (Exception e) { e.printStackTrace(); } } } class Person { public Person() { System.out.println("create Person"); } }
運(yùn)行結(jié)果:
create Person cls=class com.bjpowernode.test.Person
說(shuō)明:
(01) Person類(lèi)的完整包名是"com.bjpowernode.test.Person"。而 Class.forName("com.bjpowernode.test.Person"); 這一句的作用是,就是根據(jù)Person的包名來(lái)獲取Person的Class對(duì)象。
(02) 接著,我們調(diào)用Class對(duì)象的newInstance()方法,創(chuàng)建Person對(duì)象。
現(xiàn)在,我們知道了“java反射機(jī)制”的概念以及它的原理。有了這個(gè)總體思想之后,接下來(lái),我們可以開(kāi)始對(duì)反射進(jìn)行深入研究了。
Class 詳細(xì)說(shuō)明
1 獲取Class對(duì)象的方法
我這里總結(jié)了4種常用的“獲取Class對(duì)象”的方法:
方法1:Class.forName("類(lèi)名字符串") (注意:類(lèi)名字符串必須是全稱(chēng),包名+類(lèi)名)
方法2:類(lèi)名.class
方法3:實(shí)例對(duì)象.getClass()
方法4:"類(lèi)名字符串".getClass()
下面,我們通過(guò)示例演示這4種方法。示例如下(Demo2.java):
package com.bjpowernode.test; import java.lang.Class; public class Demo2 { public static void main(String[] args) { try { // 方法1:Class.forName("類(lèi)名字符串") (注意:類(lèi)名字符串必須是全稱(chēng),包名+類(lèi)名) //Class cls1 = Class.forName("com.bjpowernode.test.Person"); Class<?> cls1 = Class.forName("com.bjpowernode.test.Person"); //Class<Person> cls1 = Class.forName("com.bjpowernode.test.Person"); // 方法2:類(lèi)名.class Class cls2 = Person.class; // 方法3:實(shí)例對(duì)象.getClass() Person person = new Person(); Class cls3 = person.getClass(); // 方法4:"類(lèi)名字符串".getClass() String str = "com.bjpowernode.test.Person"; Class cls4 = str.getClass(); System.out.printf("cls1=%s, cls2=%s, cls3=%s, cls4=%s\n", cls1, cls2, cls3, cls4); } catch (Exception e) { e.printStackTrace(); } } } class Person { public Person() { System.out.println("create Person"); } }
運(yùn)行結(jié)果:
create Person cls1=class com.bjpowernode.test.Person, cls2=class com.bjpowernode.test.Person, cls3=class com.bjpowernode.test.Person, cls4=class java.lang.String
2 Class的API說(shuō)明
Class的全部API如下表:
Class的全部API如下表:
public static Class forName(String className) public static Class forName(String name, boolean initialize, ClassLoader loader) public Constructor getConstructor(Class[] parameterTypes) public Constructor[] getConstructors() public Constructor getDeclaredConstructor(Class[] parameterTypes) public Constructor[] getDeclaredConstructors() public Constructor getEnclosingConstructor() public Method getMethod(String name, Class[] parameterTypes) public Method[] getMethods() public Method getDeclaredMethod(String name, Class[] parameterTypes) public Method[] getDeclaredMethods() public Method getEnclosingMethod() public Field getField(String name) public Field[] getFields() public Field getDeclaredField(String name) public Field[] getDeclaredFields() public Type[] getGenericInterfaces() public Type getGenericSuperclass() public Annotation<A> getAnnotation(Class annotationClass) public Annotation[] getAnnotations() public Annotation[] getDeclaredAnnotations() public boolean isAnnotation() public boolean isAnnotationPresent(Class annotationClass) public boolean isAnonymousClass() public boolean isArray() public boolean isAssignableFrom(Class cls) public boolean desiredAssertionStatus() public Class<U> asSubclass(Class clazz) public Class getSuperclass() public Class getComponentType() public Class getDeclaringClass() public Class getEnclosingClass() public Class[] getClasses() public Class[] getDeclaredClasses() public Class[] getInterfaces() public boolean isEnum() public boolean isInstance(Object obj) public boolean isInterface() public boolean isLocalClass() public boolean isMemberClass() public boolean isPrimitive() public boolean isSynthetic() public String getSimpleName() public String getName() public String getCanonicalName() public String toString() public ClassLoader getClassLoader() public Package getPackage() public int getModifiers() public ProtectionDomain getProtectionDomain() public URL getResource(String name) public InputStream getResourceAsStream(String name) public Object cast(Object obj) public Object newInstance() public Object[] getSigners() public Object[] getEnumConstants() public TypeVariable[] getTypeParameters()
我們根據(jù)類(lèi)的特性,將Class中的類(lèi)分為4部分進(jìn)行說(shuō)明:構(gòu)造函數(shù),成員方法,成員變量,類(lèi)的其它信息(如注解、包名、類(lèi)名、繼承關(guān)系等等)。
2.1 構(gòu)造函數(shù)
“構(gòu)造函數(shù)”相關(guān)API
// 獲取“參數(shù)是parameterTypes”的public的構(gòu)造函數(shù) public Constructor getConstructor(Class[] parameterTypes) // 獲取全部的public的構(gòu)造函數(shù) public Constructor[] getConstructors() // 獲取“參數(shù)是parameterTypes”的,并且是類(lèi)自身聲明的構(gòu)造函數(shù),包含public、protected和private方法。 public Constructor getDeclaredConstructor(Class[] parameterTypes) // 獲取類(lèi)自身聲明的全部的構(gòu)造函數(shù),包含public、protected和private方法。 public Constructor[] getDeclaredConstructors() // 如果這個(gè)類(lèi)是“其它類(lèi)的構(gòu)造函數(shù)中的內(nèi)部類(lèi)”,調(diào)用getEnclosingConstructor()就是這個(gè)類(lèi)所在的構(gòu)造函數(shù);若不存在,返回null。 public Constructor getEnclosingConstructor()
接下來(lái),我們通過(guò)示例對(duì)這些API進(jìn)行說(shuō)明。示例代碼(DemoClassContructor.java)如下:
package com.bjpowernode.test; import java.lang.Class; import java.lang.reflect.Constructor; /** * java Class類(lèi)的Constructor相關(guān)API的測(cè)試函數(shù) * * */ public class DemoClassContructor { public static void main(String[] args) { // getDeclaredConstructor() 的測(cè)試函數(shù) testGetDeclaredConstructor() ; // getConstructor() 的測(cè)試函數(shù) testGetConstructor() ; // getEnclosingConstructor() 的測(cè)試函數(shù) testGetEnclosingConstructor() ; } /** * getDeclaredConstructor() 的測(cè)試函數(shù) */ public static void testGetDeclaredConstructor() { try { // 獲取Person類(lèi)的Class Class<?> cls = Class.forName("com.bjpowernode.test.Person"); // 根據(jù)class,獲取構(gòu)造函數(shù) Constructor cst1 = cls.getDeclaredConstructor(); Constructor cst2 = cls.getDeclaredConstructor(new Class[]{String.class}); Constructor cst3 = cls.getDeclaredConstructor(new Class[]{String.class, int.class, Gender.class}); // 根據(jù)構(gòu)造函數(shù),創(chuàng)建相應(yīng)的對(duì)象 cst1.setAccessible(true); // 因?yàn)镻erson中Person()是private的,所以這里要設(shè)置為可訪(fǎng)問(wèn) Object p1 = cst1.newInstance(); Object p2 = cst2.newInstance("Juce"); Object p3 = cst3.newInstance("Jody", 34, Gender.MALE); System.out.printf("%-30s: p1=%s, p2=%s, p3=%s\n", "getConstructor()", p1, p2, p3); } catch (Exception e) { e.printStackTrace(); } } /** * getConstructor() 的測(cè)試函數(shù) */ public static void testGetConstructor() { try { // 獲取Person類(lèi)的Class Class<?> cls = Class.forName("com.bjpowernode.test.Person"); // 根據(jù)class,獲取構(gòu)造函數(shù) //Constructor cst1 = cls.getConstructor(); // 拋出異常,因?yàn)槟J(rèn)構(gòu)造函數(shù)是private權(quán)限。 //Constructor cst2 = cls.getConstructor(new Class[]{String.class});// 拋出異常,因?yàn)樵摌?gòu)造函數(shù)是protected權(quán)限。 Constructor cst3 = cls.getConstructor(new Class[]{String.class, int.class, Gender.class}); // 根據(jù)構(gòu)造函數(shù),創(chuàng)建相應(yīng)的對(duì)象 //Object p1 = cst1.newInstance(); //cst1.setAccessible(true); // 因?yàn)镻erson中Person()是private的,所以這里要設(shè)置為可訪(fǎng)問(wèn) //Object p1 = cst1.newInstance(); //Object p2 = cst2.newInstance("Kim"); Object p3 = cst3.newInstance("Katter", 36, Gender.MALE); System.out.printf("%-30s: p3=%s\n", "getConstructor()", p3); } catch (Exception e) { e.printStackTrace(); } } /** * getEnclosingConstructor() 的測(cè)試函數(shù) */ public static void testGetEnclosingConstructor() { try { // 獲取Person類(lèi)的Class Class<?> cls = Class.forName("com.bjpowernode.test.Person"); // 根據(jù)class,調(diào)用Person類(lèi)中有內(nèi)部類(lèi)InnerA的構(gòu)造函數(shù) Constructor cst = cls.getDeclaredConstructor(new Class[]{String.class, int.class}); // 根據(jù)構(gòu)造函數(shù),創(chuàng)建相應(yīng)的對(duì)象 Object obj = cst.newInstance("Ammy", 18); System.out.printf("%-30s: obj=%s\n", "getEnclosingConstructor()", obj); } catch (Exception e) { e.printStackTrace(); } } } // 枚舉類(lèi)型。表示“性別” enum Gender{ MALE, FEMALE } // 人 class Person { private Gender gender; // 性別 private int age; // 年齡 private String name; // 姓名 private Person() { this.name = "unknown"; this.age = 0; this.gender = Gender.FEMALE; System.out.println("call--\"private Person()\""); } protected Person(String name) { this.name = name; this.age = 0; this.gender = Gender.FEMALE; System.out.println("call--\"protected Person(String name)\""); } public Person(String name, int age, Gender gender) { this.name = name; this.age = age; this.gender = gender; System.out.println("call--\"public Person(String name, int age, Gender gender)\""); } public Person(String name, int age) { this.name = name; this.age = age; this.gender = Gender.FEMALE; //內(nèi)部類(lèi)在構(gòu)造方法中 class InnerA{ } // 獲取InnerA的Class對(duì)象 Class cls = InnerA.class; // 獲取“封閉該內(nèi)部類(lèi)(InnerA)”的構(gòu)造方法 Constructor cst = cls.getEnclosingConstructor(); System.out.println("call--\"public Person(String name, int age)\" cst="+cst); } @Override public String toString() { return "("+name+", "+age+", "+gender+")"; } }
注意:若程序無(wú)法運(yùn)行,請(qǐng)檢查“forName()”中的包名是否正確!forName()的參數(shù)必須是,Person類(lèi)的完整包名。
運(yùn)行結(jié)果:
call--"private Person()" call--"protected Person(String name)" call--"public Person(String name, int age, Gender gender)" getConstructor() : p1=(unknown, 0, FEMALE), p2=(Juce, 0, FEMALE), p3=(Jody, 34, MALE) call--"public Person(String name, int age, Gender gender)" getConstructor() : p3=(Katter, 36, MALE) call--"public Person(String name, int age)" cst=public com.bjpowernode.test.Person(java.lang.String,int) getEnclosingConstructor() : obj=(Ammy, 18, FEMALE)
說(shuō)明:
(01) 首先,要搞清楚Person類(lèi),它是我們自定義的類(lèi)。專(zhuān)門(mén)用來(lái)測(cè)試這些API的。Person中有一個(gè)成員變量gender;它是Gender對(duì)象,Gender是一個(gè)枚舉類(lèi)。取值可以是MALE或者FEMALE。
(02) testGetDeclaredConstructor() 是“getDeclaredConstructor() 的測(cè)試函數(shù)”。getDeclaredConstructor()可以“獲取類(lèi)中任意的構(gòu)造函數(shù),包含public、protected和private方法”。
(03) testGetConstructor() 是“getConstructor() 的測(cè)試函數(shù)”。getConstructor()只能“獲取類(lèi)中public的構(gòu)造函數(shù)”。
(04) testGetEnclosingConstructor() 是“getEnclosingConstructor() 的測(cè)試函數(shù)”。關(guān)于getEnclosingConstructor()的介紹,官方說(shuō)法是“如果該 Class 對(duì)象表示構(gòu)造方法中的一個(gè)本地或匿名類(lèi),則返回 Constructor 對(duì)象,它表示底層類(lèi)的立即封閉構(gòu)造方法。否則返回 null。” 通俗點(diǎn)來(lái)說(shuō),就是“如果一個(gè)類(lèi)A的構(gòu)造函數(shù)中定義了一個(gè)內(nèi)部類(lèi)InnerA,則通過(guò)InnerA的Class對(duì)象調(diào)用getEnclosingConstructor()方法,可以獲取類(lèi)A的這個(gè)構(gòu)造函數(shù)”。
2.2 成員方法
“成員方法”相關(guān)API
// 獲取“名稱(chēng)是name,參數(shù)是parameterTypes”的public的函數(shù)(包括從基類(lèi)繼承的、從接口實(shí)現(xiàn)的所有public函數(shù)) public Method getMethod(String name, Class[] parameterTypes) // 獲取全部的public的函數(shù)(包括從基類(lèi)繼承的、從接口實(shí)現(xiàn)的所有public函數(shù)) public Method[] getMethods() // 獲取“名稱(chēng)是name,參數(shù)是parameterTypes”,并且是類(lèi)自身聲明的函數(shù),包含public、protected和private方法。 public Method getDeclaredMethod(String name, Class[] parameterTypes) // 獲取全部的類(lèi)自身聲明的函數(shù),包含public、protected和private方法。 public Method[] getDeclaredMethods() // 如果這個(gè)類(lèi)是“其它類(lèi)中某個(gè)方法的內(nèi)部類(lèi)”,調(diào)用getEnclosingMethod()就是這個(gè)類(lèi)所在的方法;若不存在,返回null。 public Method getEnclosingMethod()
接下來(lái),我們通過(guò)示例對(duì)這些API進(jìn)行說(shuō)明。示例代碼(DemoClassMethod.java)如下:
package com.bjpowernode.test; import java.lang.Class; import java.lang.reflect.Method; /** * java Class類(lèi)的Method相關(guān)API的測(cè)試函數(shù) * * */ public class DemoClassMethod { public static void main(String[] args) { // getDeclaredMethod() 的測(cè)試函數(shù) testGetDeclaredMethod() ; // getMethod() 的測(cè)試函數(shù) testGetMethod() ; // getEnclosingMethod() 的測(cè)試函數(shù) testGetEnclosingMethod() ; } /** * getDeclaredMethod() 的測(cè)試函數(shù) */ public static void testGetDeclaredMethod() { try { // 獲取Person類(lèi)的Class Class<?> cls = Class.forName("com.bjpowernode.test.Person"); // 根據(jù)class,調(diào)用類(lèi)的默認(rèn)構(gòu)造函數(shù)(不帶參數(shù)) Object person = cls.newInstance(); // 獲取Person中的方法 Method mSetName = cls.getDeclaredMethod("setName", new Class[]{String.class}); Method mGetName = cls.getDeclaredMethod("getName", new Class[]{}); Method mSetAge = cls.getDeclaredMethod("setAge", new Class[]{int.class}); Method mGetAge = cls.getDeclaredMethod("getAge", new Class[]{}); Method mSetGender = cls.getDeclaredMethod("setGender", new Class[]{Gender.class}); Method mGetGender = cls.getDeclaredMethod("getGender", new Class[]{}); // 調(diào)用獲取的方法 mSetName.invoke(person, new Object[]{"Jimmy"}); mSetAge.invoke(person, new Object[]{30}); mSetGender.setAccessible(true); // 因?yàn)镻erson中setGender()是private的,所以這里要設(shè)置為可訪(fǎng)問(wèn) mSetGender.invoke(person, new Object[]{Gender.MALE}); String name = (String)mGetName.invoke(person, new Object[]{}); Integer age = (Integer)mGetAge.invoke(person, new Object[]{}); mGetGender.setAccessible(true); // 因?yàn)镻erson中g(shù)etGender()是private的,所以這里要設(shè)置為可訪(fǎng)問(wèn) Gender gender = (Gender)mGetGender.invoke(person, new Object[]{}); // 打印輸出 System.out.printf("%-30s: person=%s, name=%s, age=%s, gender=%s\n", "getDeclaredMethod()", person, name, age, gender); } catch (Exception e) { e.printStackTrace(); } } /** * getMethod() 的測(cè)試函數(shù) */ public static void testGetMethod() { try { // 獲取Person類(lèi)的Class Class<?> cls = Class.forName("com.bjpowernode.test.Person"); // 根據(jù)class,調(diào)用類(lèi)的默認(rèn)構(gòu)造函數(shù)(不帶參數(shù)) Object person = cls.newInstance(); // 獲取Person中的方法 Method mSetName = cls.getMethod("setName", new Class[]{String.class}); Method mGetName = cls.getMethod("getName", new Class[]{}); //Method mSetAge = cls.getMethod("setAge", new Class[]{int.class}); // 拋出異常,因?yàn)閟etAge()是protected權(quán)限。 //Method mGetAge = cls.getMethod("getAge", new Class[]{}); // 拋出異常,因?yàn)間etAge()是protected權(quán)限。 //Method mSetGender = cls.getMethod("setGender", new Class[]{Gender.class}); // 拋出異常,因?yàn)閟etGender()是private權(quán)限。 //Method mGetGender = cls.getMethod("getGender", new Class[]{}); // 拋出異常,因?yàn)間etGender()是private權(quán)限。 // 調(diào)用獲取的方法 mSetName.invoke(person, new Object[]{"Phobe"}); //mSetAge.invoke(person, new Object[]{38}); //mSetGender.invoke(person, new Object[]{Gender.FEMALE}); String name = (String)mGetName.invoke(person, new Object[]{}); //Integer age = (Integer)mGetAge.invoke(person, new Object[]{}); //Gender gender = (Gender)mGetGender.invoke(person, new Object[]{}); // 打印輸出 System.out.printf("%-30s: person=%s\n", "getMethod()", person); } catch (Exception e) { e.printStackTrace(); } } /** * getEnclosingMethod() 的測(cè)試函數(shù) */ public static void testGetEnclosingMethod() { try { // 獲取Person類(lèi)的Class Class<?> cls = Class.forName("com.bjpowernode.test.Person"); // 根據(jù)class,調(diào)用類(lèi)的默認(rèn)構(gòu)造函數(shù)(不帶參數(shù)) Object person = cls.newInstance(); // 根據(jù)class,調(diào)用Person類(lèi)中有內(nèi)部類(lèi)InnerB的函數(shù) Method mGetInner = cls.getDeclaredMethod("getInner", new Class[]{}); // 根據(jù)構(gòu)造函數(shù),創(chuàng)建相應(yīng)的對(duì)象 mGetInner.invoke(person, new Object[]{}); System.out.printf("%-30s: person=%s\n", "getEnclosingMethod", person); } catch (Exception e) { e.printStackTrace(); } } } enum Gender{ MALE, FEMALE } class Person { private Gender gender; // 性別 private int age; // 年齡 private String name; // 姓名 public Person() { this("unknown", 0, Gender.FEMALE); } public Person(String name, int age, Gender gender) { this.name = name; this.age = age; this.gender = gender; } // 獲取”姓名“。權(quán)限是 public public String getName() { return name; } // 設(shè)置”姓名“。權(quán)限是 public public void setName(String name) { this.name = name; } // 獲取”年齡“。權(quán)限是 protected protected int getAge() { return age; } // 設(shè)置”年齡“。權(quán)限是 protected protected void setAge(int age) { this.age = age; } // 獲取“性別”。權(quán)限是 private private Gender getGender() { return gender; } // 設(shè)置“性別”。權(quán)限是 private private void setGender(Gender gender) { this.gender = gender; } // getInner() 中有內(nèi)部類(lèi)InnerB,用來(lái)測(cè)試getEnclosingMethod() public void getInner() { // 內(nèi)部類(lèi) class InnerB{ } // 獲取InnerB的Class對(duì)象 Class cls = InnerB.class; // 獲取“封閉該內(nèi)部類(lèi)(InnerB)”的構(gòu)造方法 Method cst = cls.getEnclosingMethod(); System.out.println("call--\"getInner()\" cst="+cst); } @Override public String toString() { return "("+name+", "+age+", "+gender+")"; } }
注意:若程序無(wú)法運(yùn)行,請(qǐng)檢查“forName()”中的包名是否正確!forName()的參數(shù)必須是,Person類(lèi)的完整包名。
運(yùn)行結(jié)果:
getDeclaredMethod() : person=(Jimmy, 30, MALE), name=Jimmy, age=30, gender=MALE getMethod() : person=(Phobe, 0, FEMALE) call--"getInner()" cst=public void com.bjpowernode.test.Person.getInner() getEnclosingMethod : person=(unknown, 0, FEMALE)
2.3 成員變量
“成員變量”的相關(guān)API
// 獲取“名稱(chēng)是name”的public的成員變量(包括從基類(lèi)繼承的、從接口實(shí)現(xiàn)的所有public成員變量) public Field getField(String name) // 獲取全部的public成員變量(包括從基類(lèi)繼承的、從接口實(shí)現(xiàn)的所有public成員變量) public Field[] getFields() // 獲取“名稱(chēng)是name”,并且是類(lèi)自身聲明的成員變量,包含public、protected和private成員變量。 public Field getDeclaredField(String name) // 獲取全部的類(lèi)自身聲明的成員變量,包含public、protected和private成員變量。 public Field[] getDeclaredFields() 接下來(lái),我們通過(guò)示例對(duì)這些API進(jìn)行說(shuō)明。示例代碼(DemoClassField.java)如下: package com.bjpowernode.test; import java.lang.Class; import java.lang.reflect.Field; /** * java Class類(lèi)的"成員變量"相關(guān)API的測(cè)試函數(shù) * * */ public class DemoClassField { public static void main(String[] args) { // getDeclaredField() 的測(cè)試函數(shù) testGetDeclaredField() ; // getField() 的測(cè)試函數(shù) testGetField() ; } /** * getDeclaredField() 的測(cè)試函數(shù) * getDeclaredField() 用于獲取的是類(lèi)自身聲明的所有成員遍歷,包含public、protected和private方法。 */ public static void testGetDeclaredField() { try { // 獲取Person類(lèi)的Class Class<?> cls = Class.forName("com.bjpowernode.test.Person"); // 根據(jù)class,調(diào)用類(lèi)的默認(rèn)構(gòu)造函數(shù)(不帶參數(shù)) Object person = cls.newInstance(); // 根據(jù)class,獲取Filed Field fName = cls.getDeclaredField("name"); Field fAge = cls.getDeclaredField("age"); Field fGender = cls.getDeclaredField("gender"); // 根據(jù)構(gòu)造函數(shù),創(chuàng)建相應(yīng)的對(duì)象 fName.set(person, "Hamier"); fAge.set(person, 31); fGender.setAccessible(true); // 因?yàn)?flag"是private權(quán)限,所以要設(shè)置訪(fǎng)問(wèn)權(quán)限為true;否則,會(huì)拋出異常。 fGender.set(person, Gender.FEMALE); System.out.printf("%-30s: person=%s\n", "getDeclaredField()", person); } catch (Exception e) { e.printStackTrace(); } } /** * getField() 的測(cè)試函數(shù) * getField() 用于獲取的是public的“成員” */ public static void testGetField() { try { // 獲取Person類(lèi)的Class Class<?> cls = Class.forName("com.bjpowernode.test.Person"); // 根據(jù)class,調(diào)用類(lèi)的默認(rèn)構(gòu)造函數(shù)(不帶參數(shù)) Object person = cls.newInstance(); // 根據(jù)class,獲取Filed Field fName = cls.getField("name"); Field fAge = cls.getDeclaredField("age"); // 拋出異常,因?yàn)镻erson中age是protected權(quán)限。 Field fGender = cls.getDeclaredField("gender"); // 拋出異常,因?yàn)镻erson中g(shù)ender是private權(quán)限。 // 根據(jù)構(gòu)造函數(shù),創(chuàng)建相應(yīng)的對(duì)象 fName.set(person, "Grace"); //fAge.set(person, 26); //fGender.set(person, Gender.FEMALE); System.out.printf("%-30s: person=%s\n", "getField()", person); } catch (Exception e) { e.printStackTrace(); } } } // 枚舉類(lèi)型。表示“性別” enum Gender{ MALE, FEMALE } // 人 class Person { // private。性別 private Gender gender; // protected。 年齡 protected int age; // public。 姓名 public String name; public Person() { this("unknown", 0, Gender.FEMALE); } public Person(String name, int age, Gender gender) { this.name = name; this.age = age; this.gender = gender; } @Override public String toString() { return "("+name+", "+age+", "+gender+")"; } }
注意:若程序無(wú)法運(yùn)行,請(qǐng)檢查“forName()”中的包名是否正確!forName()的參數(shù)必須是,Person類(lèi)的完整包名。
運(yùn)行結(jié)果:
getDeclaredField() : person=(Hamier, 31, FEMALE) getField() : person=(Grace, 0, FEMALE)
2.4 類(lèi)的其它信息
2.4.1 “注解”相關(guān)的API
// 獲取類(lèi)的"annotationClass"類(lèi)型的注解 (包括從基類(lèi)繼承的、從接口實(shí)現(xiàn)的所有public成員變量) public Annotation<A> getAnnotation(Class annotationClass) // 獲取類(lèi)的全部注解 (包括從基類(lèi)繼承的、從接口實(shí)現(xiàn)的所有public成員變量) public Annotation[] getAnnotations() // 獲取類(lèi)自身聲明的全部注解 (包含public、protected和private成員變量) public Annotation[] getDeclaredAnnotations() 接下來(lái),我們通過(guò)示例對(duì)這些API進(jìn)行說(shuō)明。示例代碼(DemoClassAnnotation.java)如下: package com.bjpowernode.test; import java.lang.Class; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * java Class類(lèi)getAnnotation()的測(cè)試程序 */ public class DemoClassAnnotation { public static void main(String[] args) { try { // 根據(jù)“類(lèi)名”獲取 對(duì)應(yīng)的Class對(duì)象 Class<?> cls = Class.forName("com.bjpowernode.test.Person"); // 獲取“Person類(lèi)”的注解 MyAnnotation myann = cls.getAnnotation(MyAnnotation.class); System.out.println("myann="+myann); } catch (Exception e) { e.printStackTrace(); } } } /** * MyAnnotation是自定義個(gè)一個(gè)Annotation */ @Retention(RetentionPolicy.RUNTIME) @interface MyAnnotation { } /** * MyAnnotation 是Person的注解。 */ @MyAnnotation class Person { }
注意:若程序無(wú)法運(yùn)行,請(qǐng)檢查“forName()”中的包名是否正確!forName()的參數(shù)必須是,Person類(lèi)的完整包名。
運(yùn)行結(jié)果:
myann=@com.bjpowernode.test.MyAnnotation()
說(shuō)明:
(01) MyAnnotation 是我們自定義個(gè)一個(gè)Annotation注解。若讀者不明白“注解”,可以參考博文“”TODO
(02) getAnnotation()就是獲取這個(gè)類(lèi)的注解。
1.1.1.1
2.4.2 “父類(lèi)”和“接口”相關(guān)的API
// 獲取實(shí)現(xiàn)的全部接口 public Type[] getGenericInterfaces() // 獲取父類(lèi) public Type getGenericSuperclass()
示例代碼(DemoClassInterface.java)如下:
package com.bjpowernode.test; import java.io.Serializable; import java.lang.Runnable; import java.lang.Thread; import java.lang.Class; import java.lang.reflect.Type; /** * java Class類(lèi)的有關(guān)父類(lèi)和接口的測(cè)試 */ public class DemoClassInterface { public static void main(String[] args) { try { // 根據(jù)“類(lèi)名”獲取 對(duì)應(yīng)的Class對(duì)象 Class<?> cls = Class.forName("com.bjpowernode.test.Person"); // 獲取“Person”的父類(lèi) Type father = cls.getGenericSuperclass(); // 獲取“Person”實(shí)現(xiàn)的全部接口 Type[] intfs = cls.getGenericInterfaces(); System.out.println("father="+father); for (Type t:intfs) System.out.println("t="+t); } catch (Exception e) { e.printStackTrace(); } } } /** * Person 繼承于 Object,并且實(shí)現(xiàn)了Serializable和Runnable接口 */ class Person extends Object implements Serializable, Runnable{ @Override public void run() { } }
注意:若程序無(wú)法運(yùn)行,請(qǐng)檢查“forName()”中的包名是否正確!forName()的參數(shù)必須是,Person類(lèi)的完整包名。
運(yùn)行結(jié)果:
father=class java.lang.Object t=interface java.io.Serializable t=interface java.lang.Runnable
2.4.3 剩余的API
// 獲取“類(lèi)名” public String getSimpleName() // 獲取“完整類(lèi)名” public String getName() // 類(lèi)是不是“枚舉類(lèi)” public boolean isEnum() // obj是不是類(lèi)的對(duì)象 public boolean isInstance(Object obj) // 類(lèi)是不是“接口” public boolean isInterface() // 類(lèi)是不是“本地類(lèi)”。本地類(lèi),就是定義在方法內(nèi)部的類(lèi)。 public boolean isLocalClass() // 類(lèi)是不是“成員類(lèi)”。成員類(lèi),是內(nèi)部類(lèi)的一種,但是它不是“內(nèi)部類(lèi)”或“匿名類(lèi)”。 public boolean isMemberClass() // 類(lèi)是不是“基本類(lèi)型”。 基本類(lèi)型,包括void和boolean、byte、char、short、int、long、float 和 double這幾種類(lèi)型。 public boolean isPrimitive() // 類(lèi)是不是“復(fù)合類(lèi)”。 JVM中才會(huì)產(chǎn)生復(fù)合類(lèi),在java應(yīng)用程序中不存在“復(fù)合類(lèi)”! public boolean isSynthetic()
示例代碼(DemoClassOtherAPIs.java)如下:
package com.bjpowernode.test; import java.lang.Class; import java.lang.Runnable; import java.lang.annotation.ElementType; import java.util.TreeMap; /** * java Class類(lèi)的getName(), isInterface()等測(cè)試程序 * * */ public class DemoClassOtherAPIs { public static void main(String[] args) { Class cls = DemoClassOtherAPIs.class; // 獲取“類(lèi)名” System.out.printf("%-50s:getSimpleName()=%s\n", cls, cls.getSimpleName()); // 獲取“完整類(lèi)名” System.out.printf("%-50s:getName()=%s\n", cls, cls.getName()); // 測(cè)試其它的API testOtherAPIs() ; } public static void testOtherAPIs() { // 本地類(lèi) class LocalA { } // 測(cè)試枚舉類(lèi)型。ElementType是一個(gè)枚舉類(lèi) Class elementtypeCls = ElementType.class; System.out.printf("%-50s:isEnum()=%s\n", elementtypeCls, elementtypeCls.isEnum()); // 判斷是不是類(lèi)的對(duì)象 Class demoCls = DemoClassOtherAPIs.class; DemoClassOtherAPIs demoObj = new DemoClassOtherAPIs(); System.out.printf("%-50s:isInstance(obj)=%s\n", demoCls, demoCls.isInstance(demoObj)); // 類(lèi)是不是“接口” Class runCls = Runnable.class; System.out.printf("%-50s:isInterface()=%s\n", runCls, runCls.isInterface()); // 類(lèi)是不是“本地類(lèi)”。本地類(lèi),就是定義在方法內(nèi)部的類(lèi)。 Class localCls = LocalA.class; System.out.printf("%-50s:isLocalClass()=%s\n", localCls, localCls.isLocalClass()); // 類(lèi)是不是“成員類(lèi)”。成員類(lèi),是內(nèi)部類(lèi)的一種,但是它不是“內(nèi)部類(lèi)”或“匿名類(lèi)”。 Class memCls = MemberB.class; System.out.printf("%-50s:isMemberClass()=%s\n", memCls, memCls.isMemberClass()); // 類(lèi)是不是“基本類(lèi)型”。 基本類(lèi)型,包括void和boolean、byte、char、short、int、long、float 和 double這幾種類(lèi)型。 Class primCls = int.class; System.out.printf("%-50s:isPrimitive()=%s\n", primCls, primCls.isPrimitive()); // 類(lèi)是不是“復(fù)合類(lèi)”。 JVM中才會(huì)產(chǎn)生復(fù)合類(lèi),在java應(yīng)用程序中不存在“復(fù)合類(lèi)”! Class synCls = DemoClassOtherAPIs.class; System.out.printf("%-50s:isSynthetic()=%s\n", synCls, synCls.isSynthetic()); } // 內(nèi)部成員類(lèi) class MemberB { } }
注意:若程序無(wú)法運(yùn)行,請(qǐng)檢查“forName()”中的包名是否正確!forName()的參數(shù)必須是,Person類(lèi)的完整包名。
運(yùn)行結(jié)果:
class com.bjpowernode.test.DemoClassOtherAPIs :getSimpleName()=DemoClassOtherAPIs class com.bjpowernode.test.DemoClassOtherAPIs :getName()=com.bjpowernode.test.DemoClassOtherAPIs class java.lang.annotation.ElementType :isEnum()=true class com.bjpowernode.test.DemoClassOtherAPIs :isInstance(obj)=true interface java.lang.Runnable :isInterface()=true class com.bjpowernode.test.DemoClassOtherAPIs$1LocalA :isLocalClass()=true class com.bjpowernode.test.DemoClassOtherAPIs$MemberB :isMemberClass()=true int :isPrimitive()=true class com.bjpowernode.test.DemoClassOtherAPIs :isSynthetic()=false
說(shuō)明:isSynthetic()是用來(lái)判斷Class是不是“復(fù)合類(lèi)”。這在java應(yīng)用程序中只會(huì)返回false,不會(huì)返回true。因?yàn)?,JVM中才會(huì)產(chǎn)生復(fù)合類(lèi),在java應(yīng)用程序中不存在“復(fù)合類(lèi)”!
以上所述是小編給大家介紹的Java反射機(jī)制詳解_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
Eclipse+Java+Swing+Mysql實(shí)現(xiàn)工資管理系統(tǒng)
這篇文章主要介紹了Eclipse+Java+Swing+Mysql實(shí)現(xiàn)工資管理系統(tǒng),對(duì)正在工作或者學(xué)習(xí)的你有一定的參考價(jià)值,需要的朋友可以參考一下2022-01-01eclipse漢化及jdk安裝環(huán)境配置超詳細(xì)教程(Java安裝教程)
這篇文章主要介紹了eclipse漢化及jdk安裝環(huán)境配置超詳細(xì)教程(Java安裝教程),本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03Elasticsearch模糊查詢(xún)?cè)敿?xì)介紹
這篇文章主要給大家介紹了關(guān)于Elasticsearch模糊查詢(xún)的相關(guān)資料,在數(shù)據(jù)庫(kù)查詢(xún)中模糊查詢(xún)是一種強(qiáng)大的技術(shù),可以用來(lái)搜索與指定模式匹配的數(shù)據(jù),需要的朋友可以參考下2023-09-09Java模擬登錄正方教務(wù)抓取成績(jī)、課表、空教室
這篇文章主要介紹了Java模擬登錄正方教務(wù)抓取成績(jī)、課表、空教室等信息,Java實(shí)現(xiàn)模擬登錄正方教務(wù)抓取成績(jī)、課表、空教室,通過(guò)HttpClient來(lái)模擬瀏覽器請(qǐng)求,Jsoup解析網(wǎng)頁(yè)內(nèi)容,感興趣的小伙伴們可以參考一下2016-04-04使用Java實(shí)現(xiàn)動(dòng)態(tài)生成MySQL數(shù)據(jù)庫(kù)
這篇文章主要為大家詳細(xì)介紹了如何使用Java實(shí)現(xiàn)動(dòng)態(tài)生成MySQL數(shù)據(jù)庫(kù),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-02-02