java_反射
什么是反射
概念
- 反射:将类的各个部分封装为其他对象,这就是反射机制。
java代码在内存中经历的三个阶段
1、 Source 源代码阶段
- 执行javac编译命令从.java文件到.class文件的过程都是在源代码阶段,.class字节码文件会将类分为多个部分,其中分为成员变量部分,成员方法部分,构造方法部分等。
2、 Class 类对象阶段
- 通过ClassLoader(类加载器)将字节码文件加载到内存中。
- 通过Class类对象来描述进入内存中的字节码文件的特征和行为。将成员变量、成员方法、构造方法等封装成单独的对象放入Class类对象中。
- 最后我们可以通过Class对象的一些行为创建具体的某个对象。
3、 runtime 运行时阶段
- new 类();
反射的好处
- 在程序的运行期间操作这些对象。
- 降低程序的耦合性,提高程序的可扩展性。
获取Class类对象的方法
- 获取class类对象的方式有三种,分别对应的java代码经历的三个阶段
1、 Class.forName(“全类名”);
- 将字节码文件加载进内存,返回class对象
- 多用于配置文件,将类名定义在配置文件中
2、 类名.class;
- 通过类名的属性class获取
- 多用于参数传递
3、 对象.getClass();
- getClass()方法是定义在Object类中的
- 多用于对象获取字节码
- 同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次。
1 | package top.uaoie.day03; |
反射的应用
1、 获取所有的成员变量
- Field[] getFields()
- Field getFied(String name)
- Field[] getDeclaredFields()
- Field getDeclaredFied(String name)
2、 获取所有的构造方法
- Constructor<?>[] getConstructors()
- Constructor
getConstructors(类<?>… parameterTypes) - Constructor<?>[] getDeclaredConstructors()
- Constructor
getDeclaredConstructors(类<?>… parameterTypes)
3、 获取所有的成员方法
- Method[] getMethods()
- Menthod getMethod(String name,类<?>…parameterTypes)
- Method[] getDeclaredMethods()
- Menthod getDeclaredMethod(String name,类<?>…parameterTypes)
4、 获取类名
- String getName()
以下为演示通过反射获取所有的成员变量
- 创建一个名为Person的类,里面的代码如下:
1 | package top.uaoie.domain; |
- 再新建一个名为ReflectDome02的类,里面的代码如下:
package top.uaoie.day03;
import top.uaoie.domain.Person;
import java.lang.reflect.Field;
public class ReflectDome02 {
public static void main(String[] args) throws Exception {
//获取Person的Class对象,此处是在阶段二部分获取的
//也可在第一阶段获取,如:Class.forName("top.uaoie.domain.Person");
Class p = Person.class;
//获取成员变量
Field[] fields = p.getFields();
for (Field field : fields) {
System.out.println(field);
}
System.out.println("---------------------");
Field a = p.getField("a");
System.out.println(a);
//创建一个对象
Person person = new Person();
//获取成员变量a的值
Object value = a.get(person);
System.out.println(value);
//设置成员变量a的值
a.set(person, "这是a的值");
System.out.println(person);
System.out.println("=================");
Field[] declaredFields = p.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
Field d = p.getDeclaredField("d");
//忽略访问权限修饰符
d.setAccessible(true);//暴力反射
Object value2 = d.get(person);
System.out.println(value2);
}
}
小结
- 获取类的class对象有多种方法,其中使用Class.forName可以通过读取配置文件获取全类名
- Class.forName和getField等类是代码会报错是因为传入的是字符串,所有可能不存在这个类获或者方法,所以需要处理异常
- 通过反射可以直接访问到任何成员变量名,不受访问修饰符的限制
- 可以setAccessible设置为true来暴力反射获取或者更改成员变量的值
- 本文作者: Juaoie
- 本文链接: http://uaoie.top/2020/02/23/java/java_反射/
- 版权声明: 本博客所有文章除特别声明外,均采用 Apache License 2.0 许可协议。转载请注明出处!