傻瓜教你反射(四)---- Method

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
  • 第二個可變參數 : 是該方法的參數

總結
對于任意一個類,都能知道這個類的所以屬性和方法;對于任何一個對象,都能夠調用它的任何一個方法和屬性;這樣動態獲取新的以及動態調用對象方法的功能就叫做反射。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容