Java 中的 getTypeParameters()、 getReturnType()

Method 类的 java.lang.reflect.Method.getTypeParameters() 方法返回由该 Method 对象的泛型声明声明的 TypeVariable 对象数组,按声明顺序排列。数组的元素表示 Method 声明的类型变量对象。
如果方法对象泛型声明不包含类型变量,则此 getTypeParameters() 返回长度为 0 的数组。

句法:

public TypeVariable<Method>[] getTypeParameters()

返回值:此方法返回由此 Method 对象的泛型声明声明的 TypeVariable 对象数组

例外:如果此 Method 对象的通用签名与 JVM 规范中指定的格式不匹配,则此方法将返回 GenericSignatureFormatError。

下面的程序说明了 Method 类的 getTypeParameters() 方法:

示例 1: 说明:此代码获取类的所有方法的列表。然后通过循环迭代这些方法并获取 TypeVariable(如果在声明这些方法时定义了某些 TypeVariable)。
如果有一些 TypeVariable 可用于这些方法,则打印 TypeVariable 名称。

 

/*
* Program Demonstrate getTypeParameters() method
* of Method Class.
*/
import java.lang.reflect.Method;
import java.lang.reflect.TypeVariable;
 
public class GFG {
 
    // In this method, there is a
    // Type parameter N which extends Number class
    public <N extends Number> void getSampleMethod(N n)
    {
    }
 
    // create main method
    public static void main(String args[])
    {
 
        try {
 
            // create class object for class name GFG
            Class c = GFG.class;
 
            // get list of all Method objects of class GFG
            Method[] methods = c.getMethods();
 
            // loop through all methods and
            // try to get Type Parameter of Method
            for (Method m : methods) {
 
                // get TypeVariable array by getTypeParameters() method
                TypeVariable[] types = m.getTypeParameters();
 
                // print Type Parameter details for every TypeVariable
                for (TypeVariable t : types) {
 
                    // print type parameter name
                    // along with there method name
                    System.out.println("Type variable for Method Name "
                                       + m.getName() + " is "
                                       + t.getName());
                }
            }
        }
        catch (Exception e) {
 
            // print Exception Message if
            // any exception occurred in program
            e.printStackTrace();
        }
    }
}
输出:
Type variable for Method Name getSampleMethod is N

示例2:在该程序中,方法的类型参数不只一种。在此程序中,使用 getTypeParameter() 函数获取类型参数并打印这些类型参数的详细信息。

 

/*
* Program Demonstrate getTypeParameters() method
* of Method Class having more than one type
parameter of methods
*/
import java.lang.*;
 
public class GFG {
 
    // In this method,
    // there are three Type parameters
    // N which extends Number class,
    // E extends RuntimeException Class
    // and C extends Character class.
    public <N extends Number,
                      E extends RuntimeException,
                                C extends Character> void
    getSampleMethod(N n) throws E
    {
    }
 
    // In this method,
    // there are Two Type parameters :
    // A which extends the ArrayList class,
    // L extends the LinkedList class
    public <A extends ArrayList, L extends LinkedList> L
    SetSampleMethod(A a, L l)
    {
        return l;
    }
 
    // create main method of class
    public static void main(String args[])
    {
 
        try {
 
            // create class object for
            // class name GFG to get methods list
            // of GFG class
            Class c = GFG.class;
 
            // get list of all Method objects of
            // class GFG in array of Methods
            Method[] methods = c.getMethods();
 
            // loop through all methods and
            // try to get Type Parameter of Method
            for (Method m : methods) {
 
                // get TypeVariable array by
                // getTypeParameters method
                TypeVariable[] types = m.getTypeParameters();
 
                // If there are 1 or more than 1
                // type variables for the current
                // method of loop then print method name
                if (types.length > 0)
                    System.out.println("\nType variable Details"
                                       + " for Method Name "
                                       + m.getName());
 
                // print Type Parameter details
                // for Current Method of loop
                for (TypeVariable t : types) {
                    // get bounds for current TypeVariable
                    // and print the Name of TypeVariable and bounds
                    Type[] bounds = t.getBounds();
 
                    // print TypeVariable name and Bounds
                    System.out.println("Name : "
                                       + t.getName());
                    System.out.println("Bounds : "
                                       + Arrays.toString(bounds));
                }
            }
        }
        catch (Exception e) {
            // print Exception message if some Exception occurs
            e.printStackTrace();
        }
    }
}
输出:
Type variable Details for Method Name getSampleMethod
Name : N
Bounds : [class java.lang.Number]
Name : E
Bounds : [class java.lang.RuntimeException]
Name : C
Bounds : [class java.lang.Character]

Type variable Details for Method Name SetSampleMethod
Name : A
Bounds : [class java.util.ArrayList]
Name : L
Bounds : [class java.util.LinkedList]

参考:https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Method.html#getTypeParameters–

 getReturnType() 方法

先决条件:Java 中的 Java.lang.Class 类 |集1、Java中的Java.lang.Class类|套装2
java.lang.reflectMethod 类有助于获取类或接口上单个方法的信息。该类还提供对类方法的访问并在运行时调用它们。
Method类的getReturnType()方法 
每个方法都有一个返回类型,无论是 void、int、double、string 还是任何其他数据类型。 Method 类的 getReturnType() 方法返回一个 Class 对象,该对象表示返回类型,在创建方法时在方法中声明。
句法: 
 

public Class<?> getReturnType()

参数:该方法不带任何参数。
返回值:该方法返回一个 Class 对象,表示该方法对象的正式返回类型。
下面的程序说明了 Method 类的 getReturnType() 方法:
程序 1:下面的程序打印作为程序主方法中输入提供的类的某些特定方法的返回类型。
 

爪哇

 

/*
* Program Demonstrate how to apply getReturnType() method
* of Method Class.
*/
import java.lang.reflect.Method;
 
public class GFG {
 
    // Main method
    public static void main(String[] args)
    {
        try {
            // Create class object
            Class classobj = demoForReturnParam.class;
 
            // Get Method Object
            Method[] methods = classobj.getMethods();
 
            // Iterate through methods
            for (Method method : methods) {
 
                // We are only taking method defined in the demo class
                // We are not taking other methods of the object class
                if (method.getName().equals("setValue")
                    || method.getName().equals("getValue")
                    || method.getName().equals("setManyValues")) {
                    // apply getReturnType() method
                    Class returnParam = method.getReturnType();
 
                    // print return Type class object of method Object
                    System.out.println("\nMethod Name : "
                                       + method.getName());
 
                    System.out.println("Return Type Details: " + returnParam.getName());
                }
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
}
 
// A simple class
class demoForReturnParam {
 
    // Method returning int value
    public int setValue()
    {
        System.out.println("setValue");
        return 24;
    }
 
    // Method returning string value
    public String getValue()
    {
        System.out.println("getValue");
        return "getValue";
    }
 
    // Method returning nothing
    public void setManyValues(int value1, String value3)
    {
        System.out.println("setManyValues");
    }
}
输出: 
Method Name : setManyValues
Return Type Details: void

Method Name : getValue
Return Type Details: java.lang.String

Method Name : setValue
Return Type Details: int

 

程序2:下面的程序打印程序主方法中提供的类的所有方法的返回类型。
 

爪哇

 

/*
* Program Demonstrate how to apply getReturnType() method
* of Method Class.
*/
import java.lang.reflect.Method;
 
public class GFG {
 
    // Main method
    public static void main(String[] args)
    {
        try {
            // Create class object
            Class classobj = GFG.class;
 
            // Get Method Object
            Method[] methods = classobj.getMethods();
 
            // Iterate through methods
            for (Method method : methods) {
 
                // Apply getReturnType() method
                Class returnParam = method.getReturnType();
 
                // Print return Type class object of method Object
                System.out.println("\nMethod Name : "
                                   + method.getName());
 
                System.out.println("Return Type Details: " + returnParam.getName());
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
    // Method returning int value
    public int method1()
    {
        System.out.println("method1");
        return 24;
    }
 
    // Method returning string value
    public String method2()
    {
        System.out.println("method2");
        return "method3";
    }
 
    // Method returning nothing
    public void method3(int value1, String value3)
    {
        System.out.println("method3");
    }
}
输出: 
Method Name : method3
Return Type Details: void

Method Name : method2
Return Type Details: java.lang.String

Method Name : method1
Return Type Details: int

Method Name : main
Return Type Details: void

Method Name : wait
Return Type Details: void

Method Name : wait
Return Type Details: void

Method Name : wait
Return Type Details: void

Method Name : equals
Return Type Details: boolean

Method Name : toString
Return Type Details: java.lang.String

Method Name : hashCode
Return Type Details: int

Method Name : getClass
Return Type Details: java.lang.Class

Method Name : notify
Return Type Details: void

Method Name : notifyAll
Return Type Details: void

 

说明:该程序的输出还显示除类对象中定义的方法(如 wait、equals、toString、hashCode、getClass、notify、notifyAll)之外的方法对象的结果。这些方法都是由类对象继承自java.lang lang包的超类名Object。
参考: 
getReturnType() 的 Oracle 文档

 getParameterCount() 方法

Method 类的 java.lang.reflect.Method.getParameterCount() 方法返回方法对象上声明的参数数量。

句法:

public int getParameterCount()

返回值:此方法返回在此方法对象上定义的形式参数的数量。

下面的程序说明了 Method 类的 getParameterCount() 方法:

示例 1:下面的程序返回作为输入给出的特定方法的参数数量。

 

// Program Demonstrate how to apply getParameterCount()
// method of Method Class.
  
import java.lang.reflect.Method;
  
public class GFG {
  
    // Main method
    public static void main(String[] args)
    {
  
        try {
            // create class object
            Class classobj = GFG.class;
  
            // get list of methods
            Method[] methods = classobj.getMethods();
  
            // get no of parameters for method setManyValues
            int noOfParameters = methods[0].getParameterCount();
  
            System.out.println("Method Name: "
                               + methods[0].getName());
  
            // print no of parameters
            System.out.println("No of parameters:" + noOfParameters);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
  
    // method name setManyValues
    // No of parameters is one for this method
    public void setManyValues(String parameter1)
    {
        System.out.println("setManyValues");
    }
}
输出:
Method Name: setManyValues
No of parameters:1

示例 2:下面的程序返回类中定义的所有方法的参数数量。

 

// Program Demonstrate how to apply getParameterCount() method
// of Method Class.
  
import java.lang.reflect.Method;
  
public class GFG {
  
    // Main method
    public static void main(String[] args)
    {
  
        try {
            // create class object
            Class classobj = DemoClass.class;
  
            // get list of methods
            Method[] methods = classobj.getMethods();
  
            // get no of parameters for each
            // method in list of methods
            for (Method method : methods) {
  
                // print name of method
                System.out.print("Method Name is "
                                 + method.getName());
  
                // get no of parameters for each method
                int noOfParameters = method.getParameterCount();
  
                // print no of parameters
                System.out.println(" and No of parameters = "
                                   + noOfParameters);
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
}
// Demo class to apply getParameterCount() method
class DemoClass {
  
    // method name DemoMethod1
    // No of parameters is 1 for this method
    public void DemoMethod1(String parameter1)
    {
        System.out.println("DemoMethod1");
    }
  
    // method name DemoMethod2
    // No of parameters is 2 for this method
    public void DemoMethod2(String parameter1,
                            String parameter2)
    {
        System.out.println("DemoMethod2");
    }
  
    // method name DemoMethod2
    // No of parameters is Zero for this method
    public void DemoMethod3()
    {
        System.out.println("DemoMethod3");
    }
}
输出:
Method Name is DemoMethod1 and No of parameters = 1
Method Name is DemoMethod2 and No of parameters = 2
Method Name is DemoMethod3 and No of parameters = 0
Method Name is wait and No of parameters = 2
Method Name is wait and No of parameters = 1
Method Name is wait and No of parameters = 0
Method Name is equals and No of parameters = 1
Method Name is toString and No of parameters = 0
Method Name is hashCode and No of parameters = 0
Method Name is getClass and No of parameters = 0
Method Name is notify and No of parameters = 0
Method Name is notifyAll and No of parameters = 0

说明:该程序的输出还显示除类对象中定义的方法(如 wait、equals、toString、hashCode、getClass、notify、notifyAll)之外的方法对象的结果。这些方法都是由类对象继承自java.lang lang包的超类名Object。

参考:https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Method.html#getParameterCount–

getParameterAnnotations() 方法 

getName()

getGenericReturnType() 方法

public class demo{
     public T getValue(){}
}
Explanation:
In the above method when we going to apply getGenericReturnType() method
it is going to return T as a generic return type.

getAnnotatedReturnType() 

Annotation annotation = annotatedType.getAnnotations()[0];
System.out.println("Annotation Type: "+annotation.annotationType().getName());
System.out.println("Annotation Type Str: "+annotation.toString());

Annotations: [@GFG$customAnn()]
Annotation Type: GFG$customAnn
Annotation Type Str: @GFG$customAnn()

 getExceptionTypes() 方法

Java 中的 getModifiers()

Method Class | getGenericExceptionTypes()

Method Class | getAnnotation() 

/*
 * Program Demonstrate getTypeParameters() method
 * of Method Class.
 */

import java.lang.reflect.Method;
// Java program to demonstrate how to
// apply getAnnotatedReturnType() method
// of Method Class.

import java.lang.annotation.*;
import java.lang.reflect.AnnotatedType;
import java.util.Arrays;
// Program Demonstrate getAnnotation(Class<T> annotationClass) method
// of Method Class.

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Method;

// create a custom Annotation
@Retention(RetentionPolicy.RUNTIME)
@interface Ann {

  // This annotation has two attributes.
  public String key();

  public String value();
}

// create the Main Class
public class GFG {

  // call Annotation for method and pass values for annotation
  @Ann(key = "AvengersLeader", value = "CaptainAmerica")
  public static void getCustomAnnotation()
  {

    try {

      // create class object for class name GFG
      Class c = GFG.class;

      // get method name getCustomAnnotation as Method object
      Method[] methods = c.getMethods();
      Method method = null;
      for (Method m : methods) {
        if (m.getName().equals("getCustomAnnotation"))
          method = m;
      }

      // get Annotation of Method object m by passing
      // Annotation class object as parameter
      Ann anno = method.getAnnotation(Ann.class);

      // print Annotation Details
      System.out.println("Annotation for Method Object"
          + " having name: " + method.getName());
      System.out.println("Key Attribute of Annotation: "
          + anno.key());
      System.out.println("Value Attribute of Annotation: "
          + anno.value());
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }

  // create main method
  public static void main(String args[])
  {
    getCustomAnnotation();
  }
}

 getDeclaringClass()

方法类| Java 中的 equals() 方法

First Method object from array create by getMethods():
public java.lang.String GFGClass.add(java.lang.String)
Method object created by getMethod():
public java.lang.String GFGClass.add(java.lang.String)
Both Method objects are equal

Method Class | getDeclaredAnnotations() 

方法类| Java 中的 getDefaultValue() 方法

Class getTypeParameters() 

import java.util.Arrays;
import org.apache.poi.ss.formula.functions.T;


public  class  GFG<T,W,V>{

  public static void main(String[] args)
      throws ClassNotFoundException {

    // returns the Class object for this class
    Class myClass = Class.forName("GFG");

    System.out.println("Class represented by myClass: "
        + myClass.toString());

    // Get the type parameters of myClass
    // using getTypeParameters() method
    System.out.println(
        "TypeParameters of myClass: "
            + Arrays.toString(
            myClass.getTypeParameters()));
  }
}

Class represented by myClass: class GFG
TypeParameters of myClass: [T, W, V]

Class getTypeName()

Method Class | isVarArgs() 

 Java类中的规范名称、简单名称和类名称有什么区别? - 堆栈溢出 --- What is the difference between canonical name, simple name and class name in Java Class? - Stack Overflow

java.lang.Class: What is the difference between Class.getName(), Class.getCanonicalName() and Class.getSimpleName()

getName() – returns the name of the entity (class, interface, array class, primitive type, or void) represented by this Class object, as a String.
getCanonicalName() – returns the canonical name of the underlying class as defined by the Java Language Specification.
getSimpleName() – the simple name of the underlying class as given in the source code

What does it looks like in practice?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// Primitive type
int.class.getName();          // -> int
int.class.getCanonicalName(); // -> int
int.class.getSimpleName();    // -> int
 
// Standard class
Integer.class.getName();          // -> java.lang.Integer
Integer.class.getCanonicalName(); // -> java.lang.Integer
Integer.class.getSimpleName();    // -> Integer
 
// Inner class
Map.Entry.class.getName();          // -> java.util.Map$Entry
Map.Entry.class.getCanonicalName(); // -> java.util.Map.Entry
Map.Entry.class.getSimpleName();    // -> Entry    
 
// Anonymous inner class
Class<?> anonymousInnerClass = new Cloneable() {}.getClass();
anonymousInnerClass.getName();          // -> somepackage.SomeClass$1
anonymousInnerClass.getCanonicalName(); // -> null
anonymousInnerClass.getSimpleName();    // -> // An empty string
 
// Array of primitives
Class<?> primitiveArrayClass = new int[0].getClass();
primitiveArrayClass.getName();          // -> [I
primitiveArrayClass.getCanonicalName(); // -> int[]
primitiveArrayClass.getSimpleName();    // -> int[]
 
// Array of objects
Class<?> objectArrayClass = new Integer[0].getClass();
objectArrayClass.getName();          // -> [Ljava.lang.Integer;
objectArrayClass.getCanonicalName(); // -> java.lang.Integer[]
objectArrayClass.getSimpleName();    // -> Integer[]
package com.zt.wxlow;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;


class BaseObject {

  public void getObjectName() {
    System.out.println("BaseObject");
  }
}

class SubObject extends BaseObject {

  @Override
  public void getObjectName() {
    System.out.println("SubObject");
  }
  public void getParamsLength() {
    System.out.println("no param  0000");
  }
  public void getParamsLength(String... params) {
    System.out.println("param's length is:" + params.length);
  }

  public void getParamsLength(String param1, String param2) {
    System.out.println(param1 + "-" + param2);
  }
}

public class GFG {

  private static final String BASE_OBJECT_PATH = BaseObject.class.getTypeName();
  private static final String SUB_OBJECT_PATH = SubObject.class.getTypeName();

  public static void main(String[] args) {
    try {
      GFG gfg = new GFG();
      gfg.reflectToMulityParamsMethosTest1();
      gfg.reflectToMulityParamsMethosTest2();
      try {
        gfg.reflectToMulityParamsMethosTest3();
      } catch (Throwable e) {
       e.printStackTrace();
      }
      gfg.reflectToMulityParamsMethosTest();
    } catch (Throwable e) {
      throw new RuntimeException(e);
    }
  }

  /**
   * 测试点:测试反射调用可变参数的方法
   */
  public void reflectToMulityParamsMethosTest1()
      throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
    Class sClazz = Class.forName(SUB_OBJECT_PATH);
    Object sObj = sClazz.newInstance();// 子类实例

    // 2.反射调用可变参数的方法
    Method changeMethod = sClazz.getDeclaredMethod("getParamsLength", String[].class);
    // 可变参数必须这样封装,因为java反射内部实现做了参数个数为1的判断,如果参数长度不为1,则会抛出异常
    String[] strParams = {"a", "b", "c"};
    Object[] cParams = {strParams};
    changeMethod.invoke(sObj, cParams);
  }


  /**
   * 测试点:
   * 参数为 1
   *
   * 运行如下
   * 0
   * 1
   * @throws ClassNotFoundException
   * @throws IllegalAccessException
   * @throws InstantiationException
   * @throws NoSuchMethodException
   * @throws InvocationTargetException
   */
  public void reflectToMulityParamsMethosTest2()
      throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
    Class sClazz = Class.forName(SUB_OBJECT_PATH);
    Object sObj = sClazz.newInstance();// 子类实例

    System.out.println("========= no params =========");
    Method noParamsMethod = sClazz.getDeclaredMethod("getParamsLength", null);
    noParamsMethod.invoke(sObj);
    noParamsMethod.invoke(sObj,null);
    System.out.println("========= no params =========");
    // 2.反射调用可变参数的方法
    Method changeMethod = sClazz.getDeclaredMethod("getParamsLength", String[].class);
    // 可变参数必须这样封装,因为java反射内部实现做了参数个数为1的判断,如果参数长度不为1,则会抛出异常
    String[] strParams = {};
    System.out.println(strParams.length);
    Object[] cParams = {strParams};
    System.out.println(cParams.length);
    changeMethod.invoke(sObj, cParams);
  }


  /**
   * 测试点:这个与上面差了一点点,然后一个报错 一个不报错
   * 这里离的参数个数为0,上面的参数个数为1
   * @throws ClassNotFoundException
   * @throws IllegalAccessException
   * @throws InstantiationException
   * @throws NoSuchMethodException
   * @throws InvocationTargetException
   */
  public void reflectToMulityParamsMethosTest3()
      throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
    Class sClazz = Class.forName(SUB_OBJECT_PATH);
    Object sObj = sClazz.newInstance();// 子类实例

    // 2.反射调用可变参数的方法
    Method changeMethod = sClazz.getDeclaredMethod("getParamsLength", String[].class);
    // 可变参数必须这样封装,因为java反射内部实现做了参数个数为1的判断,如果参数长度不为1,则会抛出异常
    Object[] cParams = {};
    System.out.println(cParams.length);
    changeMethod.invoke(sObj, cParams);
  }


  /**
   * 测试点:测试反射调用可变参数的方法
   */
  public void reflectToMulityParamsMethosTest()
      throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
    Class bClazz = Class.forName(BASE_OBJECT_PATH);
    Class sClazz = Class.forName(SUB_OBJECT_PATH);
    Object bObj = bClazz.newInstance();// 父类实例
    Object sObj = sClazz.newInstance();// 子类实例
    // 1.反射调用子类父类的重载方法
    // 多态+动态绑定
    Method bMethod = bClazz.getDeclaredMethod("getObjectName");
    bMethod.invoke(bObj);// 父类的bMethod调用父类的getObjectName()
    bMethod.invoke(sObj);// 父类的bMethod调用子类的getObjectName();
    Method sMethod = sClazz.getDeclaredMethod("getObjectName");
    // 不符合多态和动态绑定
    // sMethod.invoke(bObj);//sMethod调用父类的getObjectName(),会报错:java.lang.IllegalArgumentException: object is not an instance of declaring class

    sMethod.invoke(sObj);
    // 2.反射调用可变参数的方法
    Method changeMethod = sClazz.getDeclaredMethod("getParamsLength", String[].class);
    // 可变参数必须这样封装,因为java反射内部实现做了参数个数为1的判断,如果参数长度不为1,则会抛出异常
    String[] strParams = {"a", "b", "c"};
    Object[] cParams = {strParams};
    changeMethod.invoke(sObj, cParams);
    // 3.反射调用固定长度参数的方法
    Method unChangeMethod1 = sClazz.getDeclaredMethod("getParamsLength", String.class, String.class);
    unChangeMethod1.invoke(sObj, "Hello", "Java");
    // 也可以写成这样

    Class[] clazzs = {String.class, String.class};
    Method unChangeMethod2 = sClazz.getDeclaredMethod("getParamsLength", clazzs);
    unChangeMethod2.invoke(sObj, "Hello", "Java");
    // 下面的这种调用形式也是可以的,不过会报警告
    // String[] params1 = {"Hello","Java"};
    // unChangeMethod1.invoke(sObj, params1);
  }

}

【Java】Java反射调用可变参数的方法_java反射获取可变参数的方法-CSDN博客

posted @ 2024-06-28 15:05  CharyGao  阅读(67)  评论(0编辑  收藏  举报