Java 反射机制详解

tech2023-08-05  100

反射概述

在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性; 这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。本质就是 操作字节码文件。

反射相关的类(简述)

java.lang.Class 整个类的字节码,代表整个类【一个类型】 java.lang.reflect.Method 字节码中的方法字节码,代表类中的方法 java.long.reflect.Constructor 字节码中的构造方法字节码,代表类中的构造方法 java.long.reflect.Field 字节码中的属性字节码,代表类中的成员变量和实例变量

获取字节码文件(★★★★★)

第一种:Class clazz = Class.forName(“带包名的完整类名”); clazz_1 = Class.forName("java.lang.String"); //clazz_1代表String.calss文件,或者说代表String类型 第二种:Class clazz = 对象.getClass(); Date date = new Date(); Class clazz_5 = date.getClass(); //任何一个对象都有getClass()方法 第三种:Class clazz = 任何类型.class; Class clazz_7 = Integer.class; //clazz_7代表Integer类型

反射机制创建对象

获取字节码文件通过Class对象调用newInstance()完成对象的创建 调用newInstance()方法必须保证 类有无参构造方法 Class<?> classTeacher = Class.forName("reflectdemo_02.Teacher"); Object o = classTeacher.newInstance(); System.out.println(o); // reflectdemo_02.Teacher@1b6d3586

反射相关的类(详解)

(1)java.lang.Class 类 (★★★★★)

Class 类的实例表示正在运行的 Java 应用程序中的类和接口。 枚举是一种类,注释是一种接口。Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造。

常用方法

(2)java.long.reflect.Field 类 (★★★)

Field 提供有关类或接口的单个字段的信息,以及对它的动态访问权限。 反射的字段可能是一个类(静态)字段或实例字段。

常用方法
Object get(Object obj) 返回指定对象上此 Field 表示的字段的值。int getInt(Object obj) 获取 int 类型或另一个通过扩展转换可以转换为 int 类型的基本类型的静态或实例字段的值。int getModifiers() 以整数形式返回由此 Field 对象表示的字段的 Java 语言修饰符。String getName() 返回此 Field 对象表示的字段的名称。Class<?> getType() 返回一个 Class 对象,它标识了此 Field 对象所表示字段的声明类型。int hashCode() 返回该 Field 的哈希码。void set(Object obj, Object value) 将指定对象变量上此 Field 对象表示的字段设置为指定的新值。void setInt(Object obj, int i) 将字段的值设置为指定对象上的一个 int 值。String toString() 返回一个描述此 Field 的字符串。

(3)java.long.reflect.Method 类 (★★★)

Method 提供关于类或接口上单独某个方法(以及如何访问该方法)的信息。所反映的方法可能是类方法或实例方法(包括抽象方法)。

常用方法
int getModifiers() 以整数形式返回此 Method 对象所表示方法的 Java 语言修饰符。String getName() 以 String 形式返回此 Method 对象表示的方法名称。Class<?>[] getParameterTypes() 按照声明顺序返回 Class 对象的数组,这些对象描述了此 Method 对象所表示的方法的形参类型。Class<?> getReturnType() 返回一个 Class 对象,该对象描述了此 Method 对象所表示的方法的正式返回类型。int hashCode() 返回此 Method 的哈希码。Object invoke(Object obj, Object... args) 对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。(★★★)String toString() 返回描述此 Method 的字符串。

(4)java.long.reflect.Constructor 类 (★★)

Constructor 提供关于类的单个构造方法的信息以及对它的访问权限。

常用方法
int getModifiers() 以整数形式返回此 Constructor 对象所表示构造方法的 Java 语言修饰符。String getName() 以字符串形式返回此构造方法的名称。Class<?>[] getParameterTypes() 按照声明顺序返回一组 Class 对象,这些对象表示此 Constructor 对象所表示构造方法的形参类型。TypeVariable<Constructor<T>>[] getTypeParameters() 按照声明顺序返回一组 TypeVariable 对象,这些对象表示通过此 GenericDeclaration 对象所表示的一般声明来声明的类型变量。int hashCode() 返回此 Constructor 的哈希码。T newInstance(Object... initargs) 使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。(★★★)String toString() 返回描述此 Constructor 的字符串。

通过反射机制反编译

package reflectdemo_06; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ResourceBundle; /** * 使用反射机制反编译类【成员属性,成员方法,构造方法】 * @Author Nigori * @Create 2020/9/3 */ public class DecompilationAllReflectTest { public static void main(String[] args) throws Exception { //获取资源文件 ResourceBundle resource = ResourceBundle.getBundle("classinfo"); String userClass = resource.getString("userClass"); //获取字节码文件 Class<?> aClass = Class.forName(userClass); /** * 反编译【字符串拼接】 */ //创建StringBuilder StringBuilder builder = new StringBuilder(); //类结构反编译 builder.append(Modifier.toString(aClass.getModifiers())); //类修饰符 builder.append(" class "); builder.append(aClass.getSimpleName()); //类名 builder.append(" {\n"); //字段反编译 Field[] fields = aClass.getDeclaredFields(); for (Field field : fields) { builder.append("\t"); builder.append(Modifier.toString(field.getModifiers())); //字段修饰符 builder.append(" "); builder.append(field.getType().getSimpleName()); //字段类型 builder.append(" "); builder.append(field.getName()); //字段名 builder.append(";\n"); } builder.append("\n"); //构造方法反编译 Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors(); //构造方法列表 for (Constructor<?> constructor : declaredConstructors) { builder.append("\t"); builder.append(Modifier.toString(constructor.getModifiers())); //构造方法修饰符 builder.append(" "); builder.append(aClass.getSimpleName()); //构造方法名 builder.append("("); //拼接参数列表 Class<?>[] parameterTypes = constructor.getParameterTypes(); //参数列表 for (Class<?> parameterType : parameterTypes) { builder.append(parameterType.getSimpleName()); //参数类型 builder.append(","); } if (parameterTypes.length > 0) { builder.deleteCharAt(builder.length() - 1); } builder.append(") {...}\n"); } builder.append("\n"); //成员方法反编译 Method[] declaredMethods = aClass.getDeclaredMethods(); //成员方法列表 for (Method method : declaredMethods) { builder.append("\t"); builder.append(Modifier.toString(method.getModifiers())); //方法修饰符 builder.append(" "); builder.append(method.getReturnType().getSimpleName()); //方法返回值类型 builder.append(" "); builder.append(method.getName()); //方法名 builder.append("("); //拼接参数列表 Class<?>[] parameterTypes = method.getParameterTypes(); //方法参数列表 for (Class<?> type : parameterTypes) { builder.append(type.getSimpleName()); //方法参数类型 builder.append(","); } if (parameterTypes.length > 0) { builder.deleteCharAt(builder.length() - 1); } builder.append(") {...}\n"); } builder.append("}"); System.out.println(builder); } }

输出结果

public class UserService { private String userName; private String passWord; protected String userNo; public UserService(String,String,String) {...} public UserService(String,String) {...} public UserService(String) {...} public UserService() {...} public String toString() {...} public void logout() {...} public boolean login(String,String) {...} }

通过反射机制创建对象(★★★★★)

1. 获取类的字节码 2. 通过字节码获取有/无参构造方法 3. 调用newInstance()方法创建对象

Class<?> aClass = Class.forName("reflectdemo_07.User"); //获取类的字节码 //无参构造方法创建对象 Object o = aClass.newInstance(); System.out.println(o); //有参构造方法创建对象【推荐】 Constructor<?> newObj = aClass.getDeclaredConstructor(int.class,String.class); Object obj = newObj.newInstance(1015, "小王"); System.out.println(obj);

反射机制设置/获取字段值(★★★★★)

1. 获取类的字节码 2. 创建对象 3. 获得指定的字段名 4. 使用字段对象.set(Object obj,Object value)方法设置值 5. 使用字段对象.get(Object obj)方法获取值

package reflectdemo_04; import java.lang.reflect.Field; /** * 通过反射机制设置/获取属性值 * @Author Nigori * @Create 2020/9/2 */ public class ReflectGetValueTest { public static void main(String[] args) throws Exception { Class<?> aClass = Class.forName("reflectdemo_04.Student"); Object student = aClass.newInstance(); Field teacherName = aClass.getDeclaredField("teacherName"); teacherName.set(student,"王老师"); System.out.println("teacherName:" + teacherName.get(student)); Field studentNo = aClass.getDeclaredField("studentNo"); studentNo.setAccessible(true); //字段为private时,打破封装,否则在设置/取值值时抛IllegalAccessException studentNo.set(student,10051); System.out.println("studentNo:" + studentNo.get(student)); } }

反射机制调用方法(★★★★★)

1. 获取类的字节码 2. 获得指定方法 【方法名,参数类型】 3. 使用invoke(Object obj, Object... args)调用方法

调用方法四要素:

方法名对象实参 返回值 Class<?> aClass = Class.forName("reflectdemo_07.User"); //获取类的字节码 Object obj = aClass.newInstance(); //创建对象 Method show = aClass.getDeclaredMethod("show", int.class); //获得指定方法 Object retValue = show.invoke(obj,12112); //方法的调用 System.out.println(retValue);

反射机制获取超类

package reflectdemo_07; /** * @Author Nigori * @Create 2020/9/3 */ public class SetGetTest { public static void main(String[] args) throws Exception { Class<?> aClass = Class.forName("java.lang.String"); //获取String类的超类 Class<?> superclass = aClass.getSuperclass(); System.out.println(superclass); //获取String类实现的所有接口 Class<?>[] interfaces = aClass.getInterfaces(); for (Class<?> anInterface : interfaces) { System.out.println(anInterface.getName()); } } }
最新回复(0)