Java 反射 API 教程及示例

Java 中的反射是什么?

Java 反射是指在运行时分析和修改类的所有能力的过程。Java 中的反射 API 用于在运行时操作类及其成员,包括字段、方法、构造函数等。

Java 中反射 API 的一个优点是,它还可以操作类的私有成员。

java.lang.reflect 包提供了许多类来实现反射。java.lang.Class 类的各种方法用于收集特定类的完整元数据。

java.lang.reflect 包中的 Class

以下是 java.lang.package 中用于实现反射的各种 Java 类列表-

  • Field:此类用于收集变量的声明信息,例如数据类型、访问修饰符、名称和值。
  • Method:此类用于收集方法的声明信息,例如访问修饰符、返回类型、名称、参数类型和异常类型。
  • Constructor:此类用于收集构造函数的声明信息,例如访问修饰符、名称和参数类型。
  • Modifier:此类用于收集有关特定访问修饰符的信息。

java.lang.Class 中使用的方法

  • Public String getName ():返回类的名称。
  • public Class getSuperclass():返回超类引用。
  • Public Class[] getInterfaces():返回由指定类实现的接口数组。
  • Public int getModifiers():返回一个整数值,表示指定类的修饰符,需要将其作为参数传递给“public static String toString (int i )”方法,该方法返回给定类的访问说明符。

如何获取类的完整信息

要获取有关类的变量、方法和构造函数的信息,我们需要创建该类的对象。

Methods used in java.lang.Class

public class Guru99ClassObjectCreation {
	public static void main (String[] args) throws ClassNotFoundException {
		//1 - By using Class.forname() method 
		Class c1 = Class.forName("Guru99ClassObjectCreation"); 
		//2- By using getClass() method 
		Guru99ClassObjectCreation guru99Obj = new Guru99ClassObjectCreation();
		Class c2 = guru99Obj.getClass();
		//3- By using .class 
		Class c3= Guru99ClassObjectCreation.class;
		}
	}
  • 以下示例显示了创建“class”类对象的不同方法。
  • 示例 1:如何获取类元数据

    以下示例显示了如何获取类的元数据,例如:类名、超类名、实现的接口以及类的访问修饰符。

    我们将获取名为 Guru99Base.class 的类的元数据。

    Get Metadata of Class

    import java.io.Serializable;
    public abstract class Guru99Base implements Serializable,Cloneable {
    }
    
    1. 类名是:Guru99Base
    2. 它的访问修饰符是:public 和 abstract
    3. 它实现了接口:Serializable 和 Cloneable
    4. 由于它没有显式扩展任何类,因此它的超类是:java.lang.Object

    下面的类将获取 Guru99Base.class 的元数据并打印出来。

    Get Metadata of Class

    import java.lang.reflect.Modifier;
    public class Guru99GetclassMetaData {
    
    	public static void main (String [] args) throws ClassNotFoundException { 
    	// Create Class object for Guru99Base.class 
    	Class guru99ClassObj = Guru99Base.class;
    	
    	// Print name of the class 
    	system.out.println("Name of the class is : " +guru99ClassObj.getName());
    	
    	// Print Super class name
    	system.out.println("Name of the super class is : " +guru99ClassObj.getSuperclass().getName());
    	
    	// Get the list of implemented interfaces in the form of Class array using getInterface() method
    	class[] guru99InterfaceList = guru99classObj.getInterfaces();
    	
    	// Print the implemented interfaces using foreach loop 
    	system.out.print("Implemented interfaces are : ");
    	for (Class guru99class1 : quru99 InterfaceList)	{
    		system.out.print guru99class1.getName() + " ");
    	}
    	system.out.println();
    	
    	//Get access modifiers using get Modifiers() method and toString() method of java.lang.reflect.Modifier class
    	int guru99AccessModifier= guru99classObj.getModifiers(); 
    	// Print the access modifiers
    	System.Out.println("Access modifiers of the class are : " +Modifier.tostring(guru99AccessModifier));
    	
    	}
    }
    
    1. 使用 getName 方法打印类名。
    2. 使用 getSuperClass().getName() 方法打印超类名。
    3. 打印实现的接口名称。
    4. 打印类使用的访问修饰符。

    Get Metadata of Class

    Get Metadata of Class

    示例 2:如何获取变量元数据

    以下示例显示了如何获取变量元数据。

    在此,我们创建一个名为 Guru99VariableMetaData.class 的类,其中包含一些变量。

    package guru;
    public class Guru99VariableMetaData {				
                   public static int guru99IntVar1=1111;
                   static int guru99IntVar2=2222;							
                   static String guru99StringVar1="guru99.com";							
                    static String guru99StringVar2="Learning Reflection API";    
    }	
    
    获取上述类中变量元数据的步骤。
    1. 创建上述类的类对象,即 Guru99VariableMetaData.class,如下所示。
        Guru99VariableMetaData  guru99ClassVar  = new Guru99VariableMetaData();
        Class  guru99ClassObjVar  = guru99ClassVar.getClass();
    2. 使用 getFields() 或 getDeclaredFields() 方法以字段数组的形式获取元数据,如下所示。
      Field[]  guru99Field1= guru99ClassObjVar .getFields();
      Field[]  guru99Fiel2= guru99ClassObjVar .getDeclaredFields();

    getFields() 方法返回指定类及其超类的公共变量的元数据。

    getDeclaredFields() 方法仅返回指定类的所有变量的元数据。

    1. 使用“public String getName()”方法获取变量名称。
    2. 使用“public Class getType()”方法获取变量的数据类型。
    3. 使用“public xxx get (Field)”方法获取变量的值。

      在此,xxx 可以是字节、短整型或任何我们想获取的值类型。

    4. 使用 getModifier() 和 Modifier.toString(int i) 方法获取变量的访问修饰符。

      在此,我们编写一个类来获取 Guru99VariableMetaData.class 类中存在的变量的元数据。

      Get Metadata of Variable

      package guru;
      import java.lang.reflect.Field; 
      
      public class Guru99VariableMetaDataTest {
      	public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException { 
      	// Create Class object for Guru99VariableMetaData.class 
      	Guru99VariableMetaData guru99ClassVar = new Guru99VariableMetaData(); 
      	Class guru99ClassObjVar = guru99ClassVar.getClass();
      	
      	// Get the metadata of all the fields of the class Guru99VariableMetaData 
      	Field[] guru99Field1= guru99ClassObjVar.getDeclaredFields();
      	
      	// Print name, datatypes, access modifiers and values of the varibales of the specified class 
      	for(Field field : guru99Field1) { 
      	System.out.println("Variable name : "+field.getName());
      	System.out.println("Datatypes of the variable :"+field.getType());
      	
      	int guru99AccessModifiers = field.getModifiers();
      	System.out.printlln("Access Modifiers of the variable : "+Modifier.toString(guru99AccessModifiers));
      	System.out.println("Value of the variable : "+field.get(guru99ClassVar));
      	System.out.println();
      	system.out.println("* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *") ;
      	}
      	}
      }
      
      1. 为 Guru99VariableMetaData.class 创建了类对象。
      2. 在 Field 数组中获取了所有变量的元数据。
      3. 打印了 Guru99VariableMetaData.class 类中所有变量的名称。
      4. 打印了 Guru99VariableMetaData.class 类中所有变量的数据类型。
      5. 打印了 Guru99VariableMetaData.class 类中所有变量的访问修饰符。
      6. 打印了 Guru99VariableMetaData.class 类中所有变量的值,并打印了 Guru99VariableMetaData.class 类中所有变量的数据类型。

      Get Metadata of Method

      Get Metadata of Method

      示例 3:如何获取方法元数据

      以下示例显示了如何获取方法元数据。

      在此,我们创建一个名为 Guru99MethodMetaData.class 的类,其中包含一些方法。

      Get Metadata of Method

      package guru;		
      import java.sql.SQLException;		
      public class Guru99MethodMetaData {   				
      
      	public void guru99Add(int firstElement, int secondElement , String result) 									
          throws ClassNotFoundException, ClassCastException{			
                System.out.println("Demo method for Reflextion  API");					
          }	
          public String guru99Search(String searchString) 			
          throws ArithmeticException, InterruptedException{			
              System.out.println("Demo method for Reflection API");					
      		return null;					
          }	
      	public void guru99Delete(String deleteString) 					
      	throws SQLException{			
      	    System.out.println("Demo method for Reflection API");					
          }	
      }

      获取上述类中方法元数据的步骤。

      1. 创建上述类的类对象,即 Guru99MethodMetaData.class,如下所示。
        Guru99MethodMetaData  guru99ClassVar  = new Guru99MethodMetaData  ();
        Class  guru99ClassObjVar  = guru99ClassVar.getClass();
      2. 使用 getMethods() 和 getDeclaredMethods() 方法以 Method 数组的形式获取方法信息,如下所示。
        Method[]  guru99 Method 1= guru99ClassObjVar .get Methods();
        Method []  guru99 Method 2= guru99ClassObjVar .getDeclared Method s();

        getMethods() 方法返回指定类及其超类的公共方法的元数据。

        getDeclaredMethods() 方法仅返回指定类的所有方法的元数据。

      3. 使用getName() 方法获取方法名称。
      4. 使用getReturnType() 方法获取方法的返回类型。
      5. 使用 getModifiers()Modifiers.toString(int i) 方法获取方法的访问修饰符。
      6. 使用 getParameterTypes() 方法获取方法参数类型,该方法返回一个类数组。
      7. 使用 getExceptionTypes() 方法获取抛出的异常,该方法返回一个类数组。

      在此,我们编写一个类来获取 Guru99MethodMetaData.class 类中存在的方法的元数据。

      Get Metadata of Method

      package guru;
      import java.lang.reflect.Method;
      import java.lang.reflect.Modifier;
      
      public class Guru99MethodMetaDataTest { 
      
      	public static void main (String[] args) {
      		// Create Class object for Guru99Method MetaData.class 
      		class guru99ClassObj = Guru99MethodMetaData.class;
      
      		// Get the metadata or information of all the methods of the class using getDeclaredMethods() 
      		Method[] guru99Methods=guru99classObj.getDeclaredMethods();
      
      		for(Method method : guru99Methods) { 
      		// Print the method names
      		System.out.println("Name of the method : "+method.getName());
      		
      		// Print return type of the methods 
      		System.out.println("Return type of the method : "+method.getReturnType());
      		
      		//Get the access modifier list and print
      		int guru99ModifierList = method.getModifiers(); 
      		System.Out.printlin ("Method access modifiers : "+Modifier.toString(guru99ModifierList));
      		
      		// Get and print parameters of the methods 
      		Class[] guru99ParamList= method.getParameterTypes(); 
      		system.out.print ("Method parameter types : "); 
      		for (Class class1 : guru99ParamList){ 
      			System.out.println(class1.getName()+" ");
      		}
              System.out.println();
      		
      		// Get and print exception thrown by the method 
      		Class[] guru99ExceptionList = method. getExceptionTypes(); 
      		system.out.print("Excpetion thrown by method :"); 
      		for (Class class1 : guru99ExceptionList) {
      			System.out.println (class1.getName() +" "):
      		} 
      		System.Out.println(); 
      		system.out.println("* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ");
      		
      		}
       
      	}
      }
      
      1. 为 Guru99MethodMetaData.class 创建了类对象。
      2. 在 Method 数组中获取了所有方法的元数据。
      3. 打印了 Guru99MethodMetaData.class 类中所有方法的名称。
      4. 打印了 Guru99MethodMetaData.class 类中方法的返回类型。
      5. 打印了 Guru99MethodMetaData.class 类中方法的访问修饰符。
      6. 打印了 Guru99MethodMetaData.class 中方法的参数类型。
      7. 打印了 Guru99MethodMetaData.class 中由方法抛出的异常。

        Get Metadata of Method

      Get Metadata of Method

      示例 4:如何获取构造函数元数据

      以下示例显示了如何获取构造函数元数据。

      在此,我们创建一个名为 Guru99Constructor.class 的类,其中包含不同的构造函数。

       Get Metadata of Constructors

      package guru;		
      
      import java.rmi.RemoteException;		
      import java.sql.SQLException;		
      
      public class Guru99Constructor {				
      
      	public Guru99Constructor(int no) throws ClassCastException ,ArithmeticException{  }							
      	public Guru99Constructor(int no, String name) throws RemoteException ,SQLException{  }							
      	public Guru99Constructor(int no, String name, String address) throws InterruptedException{  }							
      }

      在此,我们编写一个类来获取 Guru99Constructor.class 类中存在的构造函数的元数据。

      Get Metadata of Constructors

      package guru;
      import java.lang.reflect.Constructor; 
      public class Guru99ConstructorMetaDataTest {
      	
      	public static void main (String[] args) {
      		// Create Class object for Guru99Constructor.class 
      		Class guru99Class=Guru99Constructor.class;
      
      		// Get all the constructor information in the Constructor array
      		Constructor[] guru99ConstructorList = guru99Class.getConstructors();
      		
      		for (Constructor constructor : guru99ConstructorList) {
      			// Print all name of each constructor
      			System.out.println("Constrcutor name : "+constructor.getName());
      			
      			//Get and print access modifiers of each constructor 
      			int guru99Modifiers= constructor.getModifiers(); 
      			System.Out.printlin ("Constrctor modifier : "+Modifier.toString(guru99Modifiers));
      			
      			// Get and print parameter types 
      			Class[] guru99ParamList=constructor.getParameterTypes();
      			System.out.print ("Constrctor parameter types :"); 
      			for (Class class1 : guru99ParamList) { 
      				System.out.println(class1.getName() +" ");
      			}
      			System. out.println();
      
      			// Get and print exception thrown by constructors
      			Class[] guru99ExceptionList=constructor.getFxceptionTypes();
      			System.out.println("Exception thrown by constructors :"); 
      			for (Class class1 : guru99ExceptionList) { 
      				System.out.println(class1.getName() +" ");
      			} 
      			System.out.println();
      			System.out.println("*******************************************");
      		}
      	}
      }
      
      1. 为 Guru99Constructor.class 创建了类对象。
      2. 在 Constructor 数组中获取了所有构造函数的元数据。
      3. 打印了 Guru99Constructor.class 类中所有构造函数的名称。
      4. 打印了 Guru99Constructor.class 类中所有构造函数的访问修饰符。
      5. 打印了 Guru99Constructor.class 中构造函数的参数类型。
      6. 打印了 Guru99Constructor.class 中由构造函数抛出的异常。

      Get Metadata of Constructors

      Get Metadata of Constructors

      摘要

      • Java 中的反射编程有助于检索和修改有关类和类成员(如变量、方法、构造函数)的信息。
      • Java 中的反射 API 可以使用 java.lang.reflect 包中的类和 java.lang.Class 类的各种方法来实现。
      • java.lang.Class 类的一些常用方法是 getName()、getSuperclass()、getInterfaces()、getModifiers() 等。
      • java.lang.reflect 包中的一些常用类是 Field、Method、Constructor、Modifier 等。
      • 反射 API 可以访问类的私有方法和变量,这可能存在安全风险。
      • 反射 API 是 Java 提供的一项强大功能,但它也带来了一些开销,例如性能较慢、安全漏洞和权限问题。因此,反射 API 应被视为执行操作的最后手段。