Java 反射 API 教程与示例

什么是反射 Java?

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

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

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

java.lang.reflect 包中的类

以下是名单 各个 Java 类 在 java.lang.package 中实现反射-

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

java.lang.Class 中使用的方法

  • 公共字符串获取名称():返回类的名称。
  • 公共类获取超级类():返回超类引用
  • 公共类[] getInterfaces() :返回指定类实现的接口数组
  • getModifiers() 中公开: 返回一个整数值,表示指定类的修饰符,该修饰符需要作为参数传递给“公共静态字符串toString(int i)” 返回给定类的访问说明符的方法。

如何获取有关课程的完整信息

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

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 的类的元数据:

    获取类的元数据

    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 的元数据并打印它:

    获取类的元数据

    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. 打印该类使用的访问修饰符

    获取类的元数据

    获取类的元数据

    示例 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. 使用以下方法以字段数组的形式获取元数据 获取字段() or 获取声明字段() 方法如下:
      Field[]  guru99Field1= guru99ClassObjVar .getFields();
      Field[]  guru99Fiel2= guru99ClassObjVar .getDeclaredFields();

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

    获取声明字段() 方法仅返回来自指定类的所有变量的元数据。

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

      这里,xxx 可以是我们想要获取的任何类型的值的字节或短整型。

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

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

      获取变量的元数据

      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 类中所有变量的数据类型

      获取方法的元数据

      获取方法的元数据

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

      以下示例显示如何获取方法的元数据:

      在这里,我们创建一个名为 Guru99MethodMetaData .class 的类,它包含一些方法

      获取方法的元数据

      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[]  guru99 Method 1= guru99ClassObjVar .get Methods();
        Method []  guru99 Method 2= guru99ClassObjVar .getDeclared Method s();

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

        获取声明方法() 方法仅返回指定类的所有方法的元数据。

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

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

      获取方法的元数据

      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. 获取方法数组中所有方法的所有元数据
      3. 打印类 Guru99MethodMetaData.class 中存在的所有方法名称
      4. 打印 Guru99MethodMetaData.class 类中方法的返回类型
      5. 打印 Guru99MethodMetaData.class 类中所有方法的访问修饰符
      6. Guru99MethodMetaData.class 中方法的打印参数类型
      7. Guru99MethodMetaData.class 中的方法抛出了打印的异常

        获取方法的元数据

      获取方法的元数据

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

      以下示例显示如何获取构造函数的元数据:

      在这里,我们创建一个名为 Guru99Constructor.class 的类,它具有不同的构造函数:

      获取构造函数的元数据

      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 类中存在的构造函数的元数据:

      获取构造函数的元数据

      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. 获取构造函数数组中所有构造函数的所有元数据
      3. 打印类 Guru99Constructor.class 中存在的所有构造函数的名称
      4. 打印类 Guru99Constructor.class 中构造函数的所有访问修饰符
      5. Guru99Constructor.class 中构造函数的打印参数类型
      6. Guru99Constructor.class 中的构造函数抛出了打印异常

      获取构造函数的元数据

      获取构造函数的元数据

      总结

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