Field
1) Class -> Field
Class.getDeclaredField(String s)
返回一個(gè)Field 對(duì)象,該對(duì)象反映此Class對(duì)象所表示的類或接口的指定已聲明字段(包括私有成員)
Class.getDeclaredFields()
返回 Field 對(duì)象的一個(gè)數(shù)組,該數(shù)組包含此Class對(duì)象所表示的類或接口所聲明的所有字段(包括私有成員),不包括繼承屬性
Class.getField(int a)
返回一個(gè)Field 對(duì)象,它反映此Class對(duì)象所表示的類或接口的指定公共成員字段
Class.getFields()
返回一個(gè)包含某些 Field對(duì)象的數(shù)組,該數(shù)組包含此Class對(duì)象所表示的類或接口的所有可訪問公共字段。
Q6獲取屬性的值該怎么辦?怎么獲取私有屬性的值?(提示:參考前面獲得私有構(gòu)造器)
Q7怎么設(shè)置新的屬性值?能不能修改私有屬性的值?
2) Field中的方法
Field.getType():返回這個(gè)變量的類型
Field.getGenericType():如果當(dāng)前屬性有簽名屬性類型就返回,否則就返回Field.getType()
Field.getModifiers(): 獲取當(dāng)前成員變量的修飾符。
Field.get(Obj obj) : 獲取屬性值
Field.set(Obj obj,value) :重新設(shè)置新的屬性值
注意:使用反射獲取或者修改一個(gè)變量的值時(shí),編譯器不會(huì)進(jìn)行自動(dòng)裝/拆箱。
3)使用反射獲得和修改屬性值
A7
package com.testReflect;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class FieldTest {
public static void main(String[] args) throws Exception {
//使用反射第一步:獲取操作類所對(duì)應(yīng)的Class對(duì)象
//通過Class類中g(shù)etField(String name): 獲取類特定的方法,name參數(shù)指定了屬性的名稱
//拿到了Field類的實(shí)例后就可以調(diào)用其中的方法了
//方法:getModifiers() 以整數(shù)形式返回由此 Field 對(duì)象表示的字段的 Java 語言修飾符
System.out.println("修飾符: " + Modifier.toString(field.getModifiers()));
//方法:getType() 返回一個(gè) Class 對(duì)象,它標(biāo)識(shí)了此 Field 對(duì)象所表示字段的聲明類型
System.out.println("類型: "+field.getType());
//方法:get(Object obj) 返回指定對(duì)象obj上此 Field 表示的字段的值
System.out.println("屬性值: "+field.get(obj));
//方法: set(Object obj, Object value) 將指定對(duì)象變量上此 Field 對(duì)象表示的字段設(shè)置為指定的新值
System.out.println("修改屬性值后 --> get(Object obj): "+field.get(obj));
}
}
Q8 請(qǐng)問下列代碼使用出錯(cuò),并說明理由。
public class FieldA extends A {
public Integer value;
public final boolean is = true;
public static void main(String[] args) {
FieldA fielda = new FieldA();
Class cls = fielda.getClass();
Field field = cls.getField("value");
field.setInt(fielda, 23);
Field fieldis = cls.getDeclaredField("is");
fieldis.setBoolean(fieldTrouble, false);
}
}
A8
wrong1 : 無法給一個(gè) Integer 類型的變量賦整型值,必須給它賦一個(gè)
Integer 對(duì)象才可以。
使用Field.set(Object obj, Object value)方法解決這個(gè)問題:.set(cls, new Integer(23));
wrong2 : 這是因?yàn)樵陬惓跏蓟?,無形之中會(huì)有一個(gè)訪問限制阻止我們修改final類型的變量。由于 Field 繼承自 AccessibleObject , 我們可以使用 AccessibleObject.setAccessible() 方法告訴安全機(jī)制,這個(gè)變量可以訪問。
因此上面的例子中,聲明這個(gè)變量是可訪問的:field.setAccessible(true),運(yùn)行就正常了。
Method
1)Class -> Method
public Method[] getMethods(): 獲取包括自身和繼承過來的所有的public方法
public Method[] getDeclaredMethods(): 獲取自身所有的方法(訪問權(quán)限無關(guān))
public Method getMethod(String methodName): 表示調(diào)用指定的一個(gè)公共的方法(包括繼承的)
2)Method中的方法
getName():獲得完整的方法信息(包括修飾符、返回值、路徑、名稱、參數(shù)、拋出值)
getModifiers():獲得修飾符
getReturnType(): 獲得返回值
getExceptionTypes(): 獲得異常名稱
methodName(): 表示被調(diào)用方法的名字
parameterTypes(): 表示被調(diào)用方法的參數(shù)的Class類型如String.class
getAnnotations(): 獲得注解
3) 反射調(diào)用方法
java.lang.reflect.Method.invoke()方法來反射調(diào)用一個(gè)方法
public native Object invoke(Object receiver, Object... args)
throws IllegalAccessException, IllegalArgumentException, InvocationTargetException;
- 第一個(gè)參數(shù) : 方法屬于的
對(duì)象(如果是靜態(tài)方法,則可以直接傳null) - 第二個(gè)可變參數(shù) : 是該方法的參數(shù)
總結(jié)
對(duì)于任意一個(gè)類,都能知道這個(gè)類的所以屬性和方法;對(duì)于任何一個(gè)對(duì)象,都能夠調(diào)用它的任何一個(gè)方法和屬性;這樣動(dòng)態(tài)獲取新的以及動(dòng)態(tài)調(diào)用對(duì)象方法的功能就叫做反射。