天天看點

反射那點基礎-Method

@

目錄

  • 1 擷取 Method
    • 1.1 方法
    • 1.2 執行個體
  • 2 Method 的方法
    • 2.1 Java 方法基礎知識
    • 2.2 修飾符相關方法
      • 2.2.1 擷取修飾符
      • 2.2.2 判斷是否為 default 方法
      • 2.2.3 判斷是否為 bridge 方法
      • 2.2.4 判斷是否為 synthetic 方法
      • 2.3 擷取傳回值類型
    • 2.4 擷取方法名
    • 2.5 擷取傳回值
      • 2.5.1 方法
      • 2.5.2 測試
      • 2.6 參數
    • 2.7 異常
      • 2.7.1 方法
      • 2.7.2 測試
    • 2.8 注解
    • 2.9 調用相關
      • 2.9.1 通路權限控制
      • 2.9.2 方法調用
      • 2.9.3 測試

Method

類描述的是類對象的方法資訊。 其中包含了被反射方法的資訊, 通路資訊。在運作時, 我們可以通過該類進行方法的調用。

因為 Java 中的

java.lang.reflect

包下所有類的構造函數都不為 public, 同時類都是 final 類型的, 是以, 不能直接通過外部 new 來擷取該方法。

擷取所有的 public 方法,包括其父類, 接口的

public Method[] getMethods();
           

擷取指定參數的 public 方法, 包括其父類, 接口的

public Method getMethod(String name, Class<?>... parameterTypes);
           

擷取聲明(public, private, protected, friendly)的所有普通方法

public Method[] getDeclaredMethods();
           

擷取聲明(public, private, protected, friendly)的指定參數的普通方法

public Method getDeclaredMethod(String name, Class<?>... parameterTypes);
           

該執行個體稱為執行個體1。

定義父類

public class ParentClass {
    private String privateMethod(){
        return "ParentClass::privateMethod";
    }
    String defaultMethod(){
        return "ParentClass::defaultMethod";
    }
    protected String protectedMethod(){
        return "ParentClass::protectedMethod";
    }
    public String publicMethod(){
        return "ParentClass::public";
    }
}
           

定義子類

public class ChildClass extends ParentClass {
    private String childPrivateMethod(){
        return "ChildClass::childPrivateMethod";
    }
    String childDefaultMethod(){
        return "ChildClass::childDefaultMethod";
    }
    protected String childProtectedMethod(){
        return "ChildClass::childProtectedMethod";
    }
    public String childPublicMethod(){
        return "ChildClass::childPublicMethod";
    }
           

測試類

public class MethodTest {
    public static void main(String[] args) {
        Class<ChildClass> childClass = ChildClass.class;
        Method[] methods = childClass.getMethods();
        System.out.println("============getMethods================");
        for (Method method:methods) {
            System.out.println(method.getName());
        }

        Method[] dMethods = childClass.getDeclaredMethods();
        System.out.println("============getMethods================");
        for (Method method:dMethods) {
            System.out.println(method.getName());
        }
    }
}

           

輸出

反射那點基礎-Method

Method

是存儲方法相關的資訊, 是以, 其方法及屬性都跟這些相關。

下面是一個方法的屬性:

  1. 修飾符:修飾符,這是可選的,告訴編譯器如何調用該方法。定義了該方法的通路類型。
  2. 傳回值 :方法可能會傳回值。returnValueType 是方法傳回值的資料類型。有些方法執行所需的操作,但沒有傳回值。在這種情況下,returnValueType 是關鍵字void。
  3. 方法名:是方法的實際名稱。方法名和參數表共同構成方法簽名。
  4. 參數:參數像是一個占位符。當方法被調用時,傳遞值給參數。這個值被稱為實參或變量。參數清單是指方法的參數類型、順序和參數的個數。參數是可選的,方法可以不包含任何參數。
  5. 異常:方法中抛出的異常類型。
  6. 注解:方法上的注解。

在 Java 中, 修飾符以數字的形式存在, 通過 int 存儲了32位的數字, 就可以存儲多個數值, 此種存儲方式在

Modifier

中會進行講解。

public int getModifiers() {
        return modifiers;
    }
           

同樣以之前 [執行個體1] 的代碼進行測試, 重寫寫一個測試方法

public static void main(String[] args) {
        Class<ChildClass> childClass = ChildClass.class;
        Method[] methods = childClass.getMethods();
        System.out.println("============getMethods================");
        for (Method method:methods) {
            System.out.println(method.getName()+"::"+Modifier.toString(method.getModifiers()));
        }
    }
           

結果

反射那點基礎-Method

public boolean isDefault() {
        // Default methods are public non-abstract instance methods
        // declared in an interface.
        return ((getModifiers() & (Modifier.ABSTRACT | Modifier.PUBLIC | Modifier.STATIC)) ==
                Modifier.PUBLIC) && getDeclaringClass().isInterface();
    }
           

這是 Java 8 中引入的概念:預設方法是在接口中聲明的, public, 非 abstract 的實體方法(實體方法即不是 static 方法)。

在此處不展開。

public boolean isBridge() {
        return (getModifiers() & Modifier.BRIDGE) != 0;
    }
           

判斷是否為橋接方法。

public boolean isSynthetic() {
        return super.isSynthetic();
    }
           

判斷是否為 synthetic 方法。

public Class<?> getReturnType() {
        return returnType;
    }
           

public String getName() {
        return name;
    }
           

擷取傳回值的類型有兩種:

擷取到傳回值的

Class

類型的對象

public Class<?> getReturnType() {
        return returnType;
    }
           

Type

public Type getGenericReturnType() {
      if (getGenericSignature() != null) {
        return getGenericInfo().getReturnType();
      } else { return getReturnType();}
    }
           

定義類

public class Animal {
    private Map<String,Animal> friends = new HashMap<>();

    public void addFriend(String name, Animal animal){
        friends.put(name,animal);
    }

    public Animal callFriend(String name){
        return friends.get(name);
    }

    public<T extends Animal> T callFriend(String name, T unusedTypeObj){
        return (T)friends.get(name);
    }

    public static void main(String[] args) {
        Class<Animal> clazz = Animal.class;
        Method[] methods = clazz.getDeclaredMethods();
        for (Method method:methods) {
            System.out.println(method.getName()+"::"+method.getReturnType()+"::"+method.getGenericReturnType());
        }
    }
}
           
反射那點基礎-Method

擷取所有的參數, 傳回值是

Class

數組

public Class<?>[] getParameterTypes()
           

擷取所有參數, 傳回值是

Type

public Type[] getGenericParameterTypes()
           

擷取參數的所有注解

public Annotation[][] getParameterAnnotations()
           

擷取所有的異常, 傳回值是

Class

public Class<?>[] getExceptionTypes()
           

Type

public Type[] getGenericExceptionTypes()
           

擷取注解異常

public AnnotatedType[] getAnnotatedExceptionTypes()
           

public class ExceptionExample {
    public static void main(String[] args) throws Exception {
        Method m = ExceptionExample.class.getMethod("method");
        System.out.println(m.getGenericExceptionTypes()[0]);
        System.out.println(m.getExceptionTypes()[0]);
    }   
    public static <T extends Throwable> void method() throws T {}
}
           
反射那點基礎-Method

擷取聲明的所有注解

public Annotation[] getDeclaredAnnotations()
           

抑制Java的權限控制檢查:在針對非public時方法時, 可以考慮這麼用

public void setAccessible(boolean flag)
           

方法調用

public Object invoke(Object obj, Object... args)
           

使用示例1中的代碼

public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
        Class<ChildClass> childClass = ChildClass.class;
        Method[] methods = childClass.getDeclaredMethods();
        System.out.println("============getMethods================");
        ChildClass child = new ChildClass();
        for (Method method:methods) {
            method.setAccessible(true);
            System.out.println(method.invoke(child));
        }
           

如果注釋權限控制, 輸出如下

反射那點基礎-Method

取消注釋之後

反射那點基礎-Method

作者:阿進的寫字台

出處:https://www.cnblogs.com/homejim/

本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利。