Field
1) Class -> Field
Class.getDeclaredField(String s)
返回一個Field 對象
,該對象反映此Class對象所表示的類或接口的指定已聲明字段(包括私有成員
)
Class.getDeclaredFields()
返回 Field 對象的一個數組
,該數組包含此Class對象所表示的類或接口所聲明的所有字段(包括私有成員
),不包括繼承屬性
Class.getField(int a)
返回一個Field 對象
,它反映此Class對象所表示的類或接口的指定公共
成員字段
Class.getFields()
返回一個包含某些 Field對象的數組
,該數組包含此Class對象所表示的類或接口的所有可訪問公共
字段。
Q6
獲取屬性的值該怎么辦?怎么獲取私有屬性的值?(提示:參考前面獲得私有構造器)
Q7
怎么設置新的屬性值?能不能修改私有屬性的值?
2) Field中的方法
Field.getType():返回這個變量的類型
Field.getGenericType():如果當前屬性有簽名屬性類型就返回,否則就返回Field.getType()
Field.getModifiers(): 獲取當前成員變量的修飾符。
Field.get(Obj obj) : 獲取屬性值
Field.set(Obj obj,value) :重新設置新的屬性值
注意
:使用反射獲取或者修改一個變量的值時,編譯器不會進行自動裝/拆箱。
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 {
//使用反射第一步:獲取操作類所對應的Class對象
//通過Class類中getField(String name): 獲取類特定的方法,name參數指定了屬性的名稱
//拿到了Field類的實例后就可以調用其中的方法了
//方法:getModifiers() 以整數形式返回由此 Field 對象表示的字段的 Java 語言修飾符
System.out.println("修飾符: " + Modifier.toString(field.getModifiers()));
//方法:getType() 返回一個 Class 對象,它標識了此 Field 對象所表示字段的聲明類型
System.out.println("類型: "+field.getType());
//方法:get(Object obj) 返回指定對象obj上此 Field 表示的字段的值
System.out.println("屬性值: "+field.get(obj));
//方法: set(Object obj, Object value) 將指定對象變量上此 Field 對象表示的字段設置為指定的新值
System.out.println("修改屬性值后 --> get(Object obj): "+field.get(obj));
}
}
Q8
請問下列代碼使用出錯,并說明理由。
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 : 無法給一個 Integer 類型的變量賦整型值,必須給它賦一個
Integer 對象
才可以。
使用Field.set(Object obj, Object value)
方法解決這個問題:.set(cls, new Integer(23));
wrong2 : 這是因為在類初始化后,無形之中會有一個訪問限制阻止我們修改final
類型的變量。由于 Field 繼承自 AccessibleObject , 我們可以使用 AccessibleObject.setAccessible() 方法告訴安全機制,這個變量可以訪問。
因此上面的例子中,聲明這個變量是可訪問的:field.setAccessible(true)
,運行就正常了。
Method
1)Class -> Method
public Method[] getMethods()
: 獲取包括自身和繼承過來的所有的public
方法
public Method[] getDeclaredMethods()
: 獲取自身所有的方法(訪問權限無關)
public Method getMethod(String methodName)
: 表示調用指定的一個公共的方法(包括繼承
的)
2)Method中的方法
getName()
:獲得完整的方法信息(包括修飾符、返回值、路徑、名稱、參數、拋出值)
getModifiers()
:獲得修飾符
getReturnType()
: 獲得返回值
getExceptionTypes()
: 獲得異常名稱
methodName()
: 表示被調用方法的名字
parameterTypes()
: 表示被調用方法的參數的Class
類型如String.class
getAnnotations()
: 獲得注解
3) 反射調用方法
java.lang.reflect.Method.invoke()
方法來反射調用一個方法
public native Object invoke(Object receiver, Object... args)
throws IllegalAccessException, IllegalArgumentException, InvocationTargetException;
- 第一個參數 : 方法屬于的
對象
(如果是靜態
方法,則可以直接傳null
) - 第二個可變參數 : 是該方法的參數
總結
對于任意一個類,都能知道這個類的所以屬性和方法;對于任何一個對象,都能夠調用它的任何一個方法和屬性;這樣動態獲取新的以及動態調用對象方法的功能就叫做反射。