Java中的反射是什么?

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

私有成员和方法的反射也是Java类的一个优点。

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

java.lang.reflect包中的类

下面是中各种Java类的列表java.lang.package包实现反射:

  • 字段 Field:此类用于收集声明性信息,如数据类型、访问修饰符、变量的名称和值。
  • 方法 Method:一个声明性类型的方法,比如返回一个声明性的方法,类型是一个获取信息的方法。
  • 构造函数 Constructor:此类用于收集声明性信息,如访问修饰符、构造函数的名称和参数类型。
  • 修饰符 Modifier:此类用于收集有关特定访问修饰符的信息。

java.lang.Class中使用的方法

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

如何获取有关一个类的完整信息

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

Java反射API教程及示例插图

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”的对象的不同方法:

如何获取类的元数据

下面的示例演示如何获取元数据,例如:类名、超级类名、实现的接口和类的访问修饰符。

我们将得到名为Guru99的下面类的元数据基类:

Java反射API教程及示例插图1

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

得到Guru99的元数据基类然后打印:

Java反射API教程及示例插图2

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

Java反射API教程及示例插图3

如何获取变量的元数据

以下示例演示如何获取变量的元数据:

在这里,我们正在创建一个名为guru99variableMetata的类

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";    
}

获取上述类中变量的元数据的步骤:

创建上述类的类对象,即Guru99VariableMetaData.class具体如下:

Guru99VariableMetaData  guru99ClassVar  = new Guru99VariableMetaData();
  Class  guru99ClassObjVar  = guru99ClassVar.getClass();

使用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可以是一个字节,也可以是我们要获取的任何类型值的短字节。

使用getModifier()和修饰符Modifier.toString(int i)方法。

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

Java反射API教程及示例插图4

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. 为Guru99创建类对象VariableMetaData.class
  2. 获取字段数组中变量的所有元数据
  3. 打印了类Guru99中的所有变量名VariableMetaData.class
  4. 打印了Guru99类中变量的所有数据类型VariableMetaData.class
  5. 打印了Guru99类中变量的所有访问修饰符VariableMetaData.class
  6. 打印中所有变量的值打印Guru99类中变量的所有数据类型VariableMetaData.class

Java反射API教程及示例插图5

如何获取方法的元数据

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

在这里,我们用一些方法创建一个名为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");					
    }	
}

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

创建上述类的类对象,即Guru99MethodMetaData.class具体如下:

Guru99MethodMetaData  guru99ClassVar  = new Guru99MethodMetaData  ();
Class  guru99ClassObjVar  = guru99ClassVar.getClass();

使用getMethods()getDeclaredMethods()方法获取方法数组中的方法信息,如下所示:

Method[]  guru99 Method 1= guru99ClassObjVar .get Methods();
Method []  guru99 Method 2= guru99ClassObjVar .getDeclared Method s();

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

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

  1. 使用getName()方法获取方法的名称。
  2. 使用getReturnType()方法获取方法的返回类型。
  3. 使用getModifiers()Modifiers.toString(int i)方法。
  4. 使用返回类数组的getParameterTypes()方法获取方法参数类型。
  5. 使用返回类数组的getExceptionTypes()方法获取引发的异常。

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

Java反射API教程及示例插图6

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

Java反射API教程及示例插图7

如何获取构造函数的元数据

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

在这里,我们正在创建一个名为Guru99的类构造函数.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{  }							
}

这里,我们正在编写一个类来获取类Guru99中的构造函数的元数据构造函数.class:

Java反射API教程及示例插图8

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

Java反射API教程及示例插图9

Java反射总结:

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