简单概述

反射:将类的各个组成部分封装为其他对象,这就是反射机制,举例来说在一个java实体类当中,有
类名、成员变量、构造方法、成员方法,而反射封装的各个组成部分就是这些对象。
如下图:java在计算机中经历的三个阶段,也对应着创建反射的三种方式
image.png

创建反射的三种方式

  1. Class.forName(“全类名”):将字节码文件加载进内存,返回Class对象,它对应的就是上图的第一阶段(Source源代码阶段)。
  2. 类名.class:通过类名的属性class获取,对应的是第二阶段(Class类对象阶段)。
  3. 对象.getClass():getClass()方法是在Object类中定义着,对应的是第三阶段(Runtime运行时阶段)

总结:
同一个字节码文件(.class)在一次程序运行过程中,只会被加载一次,不论通过三种方式的哪一种获取的对象都是同一个,也就是说虽然创建反射有三种方式,但他们之间都是相等的,如下举例;
image.png

反射常用属性

1、Field属性(成员变量)

Field[] getFields():获取所有public修饰符的成员变量
Field getField(String name):获取单个指定名称的public修饰符的成员变量

Fields[] getDeclaredFields():获取所有的成员的变量,不考虑修饰符
Fields[] getDeclaredFidld(String name):获取单个指定名称的成员变量,不考虑修饰符
常用操作
1.1:设置值
void set(Object obj,Object value)
1.2:获取值
get(Object obj)
1.3:如果想要访问、修改不是public修饰的成员变量,就需要忽略访问权限修饰符的安全检查,把属 性设置为true即可,也称为暴力反射
setAccessible(boolean flag)

  1. @ToString
  2. public class ReflectDto {
  3. //四种修饰符
  4. public String a0 = "1";
  5. protected String a1 = "2";
  6. String a2;
  7. private String a3;
  8. }
  9. public static void main(String[] args) throws Exception {
  10. //一个实体类对象
  11. ReflectDto dto = new ReflectDto();
  12. //创建Class对象
  13. Class<ReflectDto> dtoClass = ReflectDto.class;
  14. //获取所有的public修饰的成员变量
  15. Field[] fields = dtoClass.getFields();
  16. //获取public修饰的单个成员变量
  17. Field a0 = dtoClass.getField("a0");
  18. //如果不设置a0的属性值,java默认返回的null
  19. System.out.println(a0);
  20. //得到值
  21. Object o = a0.get(dto);
  22. //设置值
  23. a0.set(dto,"李四");
  24. //获取所有的成员变量,不考虑修饰符
  25. Field[] declaredFields = dtoClass.getDeclaredFields();
  26. //获取单个的成员变量,不考虑修饰符
  27. Field a1 = dtoClass.getDeclaredField("a1");
  28. //暴力反射(再去访问不是public修饰的成员变量,需要去忽略访问修饰符的安全检查)
  29. a1.setAccessible(true);
  30. //得到值
  31. Object o1 = a1.get(dto);
  32. //设置值
  33. a1.set(dto,"王五");
  34. }

2、Constructor属性(构造器)

Constructor<?> getConstructors()
Constructor getConstructor(类<?> parameterType)

Constructor<?> getConstructors()
Constructor getConstructor(类<?> parameterType)
setAccessible(boolean flag):暴力反射

  1. @ToString
  2. @NoArgsConstructor
  3. @AllArgsConstructor
  4. public class ReflectDto {
  5. public String a0 = "1";
  6. protected String a1 = "2";
  7. int a2;
  8. private String a3;
  9. }
  10. public static void main(String[] args) throws Exception {
  11. //一个实体类对象
  12. ReflectDto dto = new ReflectDto();
  13. //创建Class对象
  14. Class dtoClass = ReflectDto.class;
  15. //获取无参构造方法
  16. Constructor constructor = dtoClass.getConstructor();
  17. //无参构造创建属性的两种方式
  18. Object o = constructor.newInstance();
  19. //如果使用无参构造创建属性,还可以进行简化,Class对象提供了一个Class.newInstance方法
  20. Object reflectDto1 = dtoClass.newInstance();
  21. //获取有参构造方法
  22. Constructor constructor1 = dtoClass.getConstructor(String.class, String.class,int.class,String.class);
  23. //创建对象
  24. Object reflectDto = constructor1.newInstance("张三", "李四",1,"赵柳");
  25. }

3、Method属性(方法对象)

Object invoke(Object obj,Object… args):执行方法
String getName:获取方法名

  1. @ToString
  2. @NoArgsConstructor
  3. @AllArgsConstructor
  4. public class ReflectDto{
  5. public String a0 = "1";
  6. protected String a1 = "2";
  7. int a2;
  8. private String a3;
  9. public void eat(){
  10. System.out.println("eat...");
  11. }
  12. public void eat(String param){
  13. System.out.println("eat..."+param);
  14. }
  15. private void eat2(){
  16. System.out.println("eat2...");
  17. }
  18. }
  19. public static void main(String[] args) throws Exception {
  20. //一个实体类对象
  21. ReflectDto dto = new ReflectDto();
  22. //创建Class对象
  23. Class dtoClass = ReflectDto.class;
  24. Method method = dtoClass.getMethod("eat");
  25. method.invoke(dto);
  26. Method eat = dtoClass.getMethod("eat", String.class);
  27. //真实的对象 实际传递的参数
  28. eat.invoke(dto,"午饭");
  29. /**
  30. * 获取所有public修饰的方法,包括他的父类方法,例如这里的ReflectDto类,他没有继承任何类,
  31. * 所以他的父类是Object,那么getMethods也会把Object的方法获取到。
  32. */
  33. Method[] methods = dtoClass.getMethods();
  34. for (Method method1 : methods) {
  35. System.out.println(method1);
  36. System.out.println("获取方法名:"+method1.getName());
  37. }
  38. }

4、getName():获取类名

5、注意点

暴力反射在成员变量、构造器和方法中都能使用。