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 )”方法,该方法返回给定类的访问说明符。
如何获取类的完整信息
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; } }
示例 1:如何获取类元数据
以下示例显示了如何获取类的元数据,例如:类名、超类名、实现的接口以及类的访问修饰符。
我们将获取名为 Guru99Base.class 的类的元数据。
import java.io.Serializable; public abstract class Guru99Base implements Serializable,Cloneable { }
- 类名是:Guru99Base
- 它的访问修饰符是:public 和 abstract
- 它实现了接口:Serializable 和 Cloneable
- 由于它没有显式扩展任何类,因此它的超类是: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 Classguru99ClassObj = 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)); } }
- 使用 getName 方法打印类名。
- 使用 getSuperClass().getName() 方法打印超类名。
- 打印实现的接口名称。
- 打印类使用的访问修饰符。
示例 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"; }
-
创建上述类的类对象,即 Guru99VariableMetaData.class,如下所示。
Guru99VariableMetaData guru99ClassVar = new Guru99VariableMetaData(); Class guru99ClassObjVar = guru99ClassVar.getClass();
-
使用 getFields() 或 getDeclaredFields() 方法以字段数组的形式获取元数据,如下所示。
Field[] guru99Field1= guru99ClassObjVar .getFields(); Field[] guru99Fiel2= guru99ClassObjVar .getDeclaredFields();
getFields() 方法返回指定类及其超类的公共变量的元数据。
getDeclaredFields() 方法仅返回指定类的所有变量的元数据。
- 使用“public String getName()”方法获取变量名称。
- 使用“public Class getType()”方法获取变量的数据类型。
-
使用“public xxx get (Field)”方法获取变量的值。
在此,xxx 可以是字节、短整型或任何我们想获取的值类型。
-
使用 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("* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *") ; } } }
- 为 Guru99VariableMetaData.class 创建了类对象。
- 在 Field 数组中获取了所有变量的元数据。
- 打印了 Guru99VariableMetaData.class 类中所有变量的名称。
- 打印了 Guru99VariableMetaData.class 类中所有变量的数据类型。
- 打印了 Guru99VariableMetaData.class 类中所有变量的访问修饰符。
- 打印了 Guru99VariableMetaData.class 类中所有变量的值,并打印了 Guru99VariableMetaData.class 类中所有变量的数据类型。
-
创建上述类的类对象,即 Guru99MethodMetaData.class,如下所示。
Guru99MethodMetaData guru99ClassVar = new Guru99MethodMetaData (); Class guru99ClassObjVar = guru99ClassVar.getClass();
-
使用 getMethods() 和 getDeclaredMethods() 方法以 Method 数组的形式获取方法信息,如下所示。
Method[] guru99 Method 1= guru99ClassObjVar .get Methods(); Method [] guru99 Method 2= guru99ClassObjVar .getDeclared Method s();
getMethods() 方法返回指定类及其超类的公共方法的元数据。
getDeclaredMethods() 方法仅返回指定类的所有方法的元数据。
- 使用getName() 方法获取方法名称。
- 使用getReturnType() 方法获取方法的返回类型。
- 使用 getModifiers() 和 Modifiers.toString(int i) 方法获取方法的访问修饰符。
- 使用 getParameterTypes() 方法获取方法参数类型,该方法返回一个类数组。
-
使用 getExceptionTypes() 方法获取抛出的异常,该方法返回一个类数组。
- 为 Guru99MethodMetaData.class 创建了类对象。
- 在 Method 数组中获取了所有方法的元数据。
- 打印了 Guru99MethodMetaData.class 类中所有方法的名称。
- 打印了 Guru99MethodMetaData.class 类中方法的返回类型。
- 打印了 Guru99MethodMetaData.class 类中方法的访问修饰符。
- 打印了 Guru99MethodMetaData.class 中方法的参数类型。
-
打印了 Guru99MethodMetaData.class 中由方法抛出的异常。
- 为 Guru99Constructor.class 创建了类对象。
- 在 Constructor 数组中获取了所有构造函数的元数据。
- 打印了 Guru99Constructor.class 类中所有构造函数的名称。
- 打印了 Guru99Constructor.class 类中所有构造函数的访问修饰符。
- 打印了 Guru99Constructor.class 中构造函数的参数类型。
- 打印了 Guru99Constructor.class 中由构造函数抛出的异常。
- 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 应被视为执行操作的最后手段。
示例 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"); } }
获取上述类中方法元数据的步骤。
在此,我们编写一个类来获取 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("* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * "); } } }
示例 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("*******************************************"); } } }