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–
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.
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()
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();
}
}
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() 方法
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]
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);
}
}