type
status
date
slug
summary
tags
category
icon
password
本文为加固前置知识
0、什么是反射
不知道的时候我以为这是一种映射关系
实则不然,反射是指在程序运行时动态地获取类的信息,包括类名、字段、方法等,从而操作类或对象的属性和方法。本质是JVM得到class对象之后,再通过class对象进行反编译,从而获取对象的各种信息
为什么需要了解反射
Java属于先编译再运行的语言,程序中对象的类型在编译期就确定下来了,而当程序在运行时可能需要动态加载某些类,这些类因为之前用不到,所以没有被加载到JVM。通过反射,可以在运行时动态地创建对象并调用其属性,不需要提前在编译期知道运行的对象是谁。
可以理解为反射其实就是直接使用类的一个逆向使用
1、举个🌰
从代码中可以看到我们使用反射调用了 setPrice 方法,并传递了 14 的值。之后使用反射调用了 getPrice 方法,输出其价格。上面的代码整个的输出结果是:
从这个简单的例子可以看出,一般情况下我们使用反射获取一个对象的步骤:
- 获取类的 Class 对象实例
- 根据 Class 对象实例获取 Constructor 对象
- 使用 Constructor 对象的 newInstance 方法获取反射类对象
而如果要调用某一个方法,则需要经过下面的步骤:
- 获取方法的 Method 对象
- 利用 invoke 方法调用方法
到这里,我们已经能够读反射的基本使用。但如果要进一步掌握反射,还需要对反射的常用 API 进行理解
2、反射常用API
参考东方玻璃大佬
在JDK中,主要由以下类来实现Java反射机制,这些类都位于java.lang.reflect包中
- Class类:代表一个类
- Constructor 类:代表类的构造方法
- Field 类:代表类的成员变量(属性)
- Method类:代表类的成员方法
在JDK中,反射相关的 API 可以分为下面几类:获取反射的 Class 对象、通过反射创建类对象、通过反射获取类属性方法及构造器。
反射获取Class
在反射中,要获取一个类或调用一个类的方法,我们首先需要获取到该类的 Class 对象。
- 非动态加载时,可通过
.class
属性或实例.getClass()
方法获取Class类
- 动态加载时,可使用
Class.forName()
和ClassLoader.loadClass()
加载并获取类对象
输入如下:
反射获取Constructor
- class.getConstructor(Class<?>... ParameterTypes) 获取class类指定参数类型的public构造方法
- class.getConstructors() 获取class类中的所有public权限的构造方法
- class.getDeclaredConstructor(Class<?>... ParameterTypes) 获取class类中的任意构造方法
- class.getDeclaredConstructors() 获取class类中的所有构造方法
输入如下:
反射获取Field
- class.getField(FieldName) 获取class类中的带public声明的FieldName变量
- class.getFields() 获取class类中的带public声明的所有变量
- class.getDeclaredField(FieldName) 获取class类中的FieldName变量
- class.getDeclaredFields() 获取class类中的所有变量
输出如下
反射获取Method
- class.getMethod(MethodName,...ParameterTypes) 获取指定方法名和指定参数的public方法
- class.getMethods() 获取class类中所有public方法
- class.getDeclaredMethod(MethodName,...ParameterTypes) 获取class类中指定方法名和指定参数的任意方法
- class.getDeclaredMethods() 获取class类的所有方法
- class.getMethod(MethodName,...ParameterTypes) 获取指定方法名和指定参数的public方法
- class.getMethods() 获取class类中所有public方法
- class.getDeclaredMethod(MethodName,...ParameterTypes) 获取class类中指定方法名和指定参数的任意方法
- class.getDeclaredMethods() 获取class类的所有方法
输出如下
反射创建对象
- 通过Class.newInstance() 调用无参构造方法创建实例 不能传递参数
- 通过Constructor.newInstance() 调用指定构造方法创建实例 可传递参数
输入如下:
反射操作属性
- Class.getField(FieldName) 获取指定名称的public属性
- Class.getDeclaredField(FieldName) 获取指定名称的任意属性
- Field.get(Object obj) 获取指定实例的值
- Field.set(Object obj,Object value) 设置指定实例的值
- Field.setAccessible(true) 突破属性权限控制
输出:
反射调用方法
- Class.getMethod(String name,Class<?>... parameterTypes) 获取指定名称和参数类型的public方法
- Class.getDeclaredMethod(String name,Class<?>... parameterTypes) 获取指定名称和参数类型的方法
- Method.setAccessible(true) 突破访问权限控制
- Method.invoke(Object obj,Object... args) 调用指定实例的方法,可传递参数
输出:
- 作者:Sh4d0w
- 链接:https://sh4d0w.blog//article/21250fad-5ffd-8037-ab94-c8c552778a3f
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。