Java反射機制是肥腸重要的概念,它的原理以及如何使用,一起來探討吧!
Java反射機制是在運行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個對象,都能夠調用它的任意一個方法和屬性;這種動態獲取的信息以及動態調用對象的方法的功能稱爲Java語言的反射機制。
上面說的是反射的官方概念,其意思也就是,正常實例化對象的方式是:1、首先引入需要的包 2、new實例化 3、取得實例化對象 。而反射機制是“反”過來,通過實例化對象,可以獲得此對象的屬性,方法,所屬類包的名稱。反射是被視爲動態語言的關鍵,反射機制允許程序在執行期藉助於 Reflection API 取得任何類的內部信息,並能直接操作任意對象的內部屬性及方法。可以降低程序的耦合度,很多框架都運用了反射。
上面提到了反射是動態語言的關鍵,那麼,上面是“動態語言”呢?
動態語言是指程序運行時,允許改變程序結構或變量類型,這種語言稱爲動態語言。C++,Java,C#都不是動態語言。儘管在這樣的定義與分類下Java不是動態語言,它卻有着一個非常突出的動態相關機制:Reflection。這個字的意思是“反射、映象、倒影”,用在Java身上指的是我們可以於運行時加載、探知、使用編譯期間完全未知的classes。
Java的反射機制有什麼功能?
- 在運行時判斷任意一個對象所屬的類;
- 在運行時構造任意一個類的對象;
- 在運行時判斷任意一個類所具有的成員變量和方法;
- 在運行時調用任意一個對象的方法;
- 生成動態代理
反射機制的相關類
類名 | 用途 |
---|---|
Class | 代表類的實體,在運行的Java應用程序中表示類和接口 |
Field | 代表類的成員變量 |
Method | 代表類的方法 |
Constructor | 代表類的構造方法 |
Class類
1、創建Person類的對象
//Person.class 代表Person類
Class c = Person.class;
//創建Person類的實例p,相當於不使用反射創建的實例:Person p = new Person();
Person p = (Person)c.newInstance();
2、通過運行時類的對象,調用其getClass()方法,返回其運行時類。
Person per = new Person();
Class clazz = per.getClass();
System.out.println(clazz);
3、獲取Class類的四種方式:
//1、調用運行時類本身的 .class 屬性
Class c1 = Person.class;
//打印TestReflection.Person
System.out.println(clazz.getName());
Class c2= String.class;
//打印java.lang.String
System.out.println(c2.getName());
//2、 通過運行時類的對象獲取
Person person = new Person();
Class c3 = person.getClass();
//打印TestReflection.Person
System.out.println(c3.getName());
//3、通過 class 的靜態方法獲取
String className = "TestReflection.Person";
Class c4 = Class.forName(className);
//打印TestReflection.Person
System.out.println(c4.getName());
//4、類的加載器
String className = "TestReflection.Person";
ClassLoader classLoader = this.getClass().getClassLoader();
Class c5 = classLoader.loadClass(className);
//打印TestReflection.Person
System.out.println(c5.getName());
Field類
1、獲取Person類的訪問控制符爲public的指定成員變量
//Person.class 代表Person類
Class c = Person.class;
//創建Person類的實例p,相當於不使用反射創建的實例:Person p = new Person();
Person p = (Person)c.newInstance();
//獲取類Person的public屬性 name
Field f1 = c.getField("name");
//設定 Person類的對象 p 的 name 屬性爲 "Nikita",當Person的name屬性的訪問控制符爲 public 時纔可設定屬性值。
f1.set(p,"Nikita");
//打印Nikita
System.out.println(p.name);
2、獲取Person類的訪問控制符爲private的指定成員變量
//獲取聲明的Person類的private屬性 age
Field f2 = c.getDeclaredField("age");
//使用反射機制訪問私有變量時必須調用 setAccessible方法設置屬性爲true,否則會報 IllegalAccessException異常
f2.setAccessible(true);
//設置Person類的對象p的age屬性值爲 34
f2.set(p,34);
//打印 34
System.out.println(p.getAge());
3、獲取Person類的所有 public屬性
Class cla = Person.class;
//getFields():獲取運行時類中及其父類中所有public屬性
Field[] fields = cla.getFields();
for(int i =0;i<fields.length;i++) {
//打印:public java.lang.String TestReflection.Person.name
System.out.println(fields[i]);
}
4、獲取 Person類的所有屬性(包括private)
Class cla = Person.class;
//getDeclaredFields():獲取運行時類本身的所有屬性(包括private)
Field[] fields1 = cla.getDeclaredFields();
for(Field f:fields1){
System.out.println(f.getName());
}
Method類
1、獲取Person類的 getAge()方法
Class c = Person.class;
Person p = (Person)c.newInstance();
//獲取Person類的 getAge方法
Method m1 = c.getMethod("getAge");
//Person類的對象p調用獲取的 getAge 方法,如果此方法有參數,invoke第二個參數是 調用getAge方法需要的參數。
m1.invoke(p);
2、獲取Person類的 display()方法
Class c = Person.class;
Person p = (Person)c.newInstance();
//獲取 Person 類的 display方法,第二個參數爲 display方法的參數類型
Method m2 = c.getMethod("display", String.class);
//調用display方法,參數爲"CHN is very good!"
m2.invoke(p,"CHN is very good!");
3、getMethods():獲取運行時類及其父類中所有聲明爲 public 的方法
Class ccc = Person.class;
Method[] method1 = ccc.getMethods();
for(Method m :method1) {
System.out.println(m);
}
4、getDeclareMethods():獲取運行時類的所有方法(包括 private)
Class ccc = Person.class;
Method[] method2 = ccc.getDeclareMethods();
for(Method m :method2) {
System.out.println(m);
}
Constructor類
獲取類中所有構造函數
String className = "TestReflection.Person";
Class c = Class.forName(className);
Constructor[] cons = c.getDeclaredConstructors();
for(Constructor con : cons){
System.out.println(con);
}
}
獲取類的完整結構
包括:註解、權限修飾符、返回值類型、方法名、形參列表、異常類型
public void test3() throws Exception{
//獲取類中方法的完整結構
Class c = Person.class;
Method[] method = c.getDeclaredMethods();
for(Method m : method) {
//1、註解
Annotation[] ann = m.getAnnotations();
for(Annotation a:ann){
System.out.print(a);
}
//2、權限修飾符
String str = Modifier.toString(m.getModifiers());
System.out.print(str+" ");
//3、返回值類型
Class returnType = m.getReturnType();
System.out.println(returnType.getName()+" ");
//4、方法名
System.out.println(m.getName());
//5、形參列表
System.out.print("(");
Class[] params = m.getParameterTypes();
for(int i = 0;i<params.length;i++){
System.out.print(params[i].getName()+" args-"+i+" ");
}
System.out.println(")");
//6、異常類型
Class [] exps = m.getExceptionTypes();
if(exps.length != 0){
System.out.print("throws ");
}
for(int i = 0;i < exps.length;i++) {
System.out.print(exps[i].getName() + "");
}
}
}