反射的概述

Java反射机制的概念

Java反射机制是指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态盗用对象方法的功能成为java语音的反射机制。

Java反射机制的作用

是用来编写一些通用性较高的代码或者框架的时候使用

反射常用对象的概述

Class:Class类的实例表示正在运行的Java应用程序中的类和接口
Constructor:关于类的单个构造方法的信息以及对它的访问权限
Field:Field提供有关类或接口的单个字段的信息,以及对它的动态访问权限
Method:Method提供关于类或接口上单独某个方法的信息

image.png

反射常用API

Class类

  • Java中java.lang.Class类用于表示一个类的字节码(.class)文件
  • 如何得到某个class文件对应的Class对象

已知类和对象的情况下:类名.class,对象.getClass() —- Object类提供
未知类和对象的情况下:Class.forName(“包名.类名”)

Class类代表某个类的字节码,并提供了加载字节码的方法:forName(“包名.类名”)
forName方法用于加载类字节码到内存中,并封装成一个Class对象

  1. package com.song.reflect;
  2. import org.junit.Test;
  3. public class ClassTest {
  4. @Test
  5. public void demo1() throws ClassNotFoundException {
  6. // 1. 通过类名.class的方式
  7. Class class1 = Person.class;
  8. System.out.println("class1:" + class1);
  9. // 2. 通过对象.getClass()的方式
  10. Person person = new Person();
  11. Class class2 = person.getClass();
  12. System.out.println("class2:" + class1);
  13. // 3. 通过Class.forName()的方式(推荐)
  14. Class class3 = Class.forName("com.song.reflect.Person");
  15. System.out.println("class3:" + class1);
  16. }
  17. }

class1:class com.song.reflect.Person
class2:class com.song.reflect.Person
class3:class com.song.reflect.Person

Constructor类

  • Constructor类的实例对象代表类的一个构造方法
  • 得到某个类所有的构造方法

Constructor[] constructors = Class.forName(“java.lang.String”).getConstructors();

  • 得到指定的构造方法并调用

Constructor constructor = Class.forName(“java.lang.String”).getConstructor(String.class);
String str = (String)constructor.newInstance(“abc”);

  • Class类的newInstance()方法用来调用类的默认构造方法

String obj = (String)Class.forName(“java.lang.String”).newInstance();

  1. package com.song.reflect;
  2. import org.junit.Test;
  3. import java.lang.reflect.Constructor;
  4. public class ConstructorTest {
  5. @Test
  6. // 获得无参数的构造方法
  7. public void demo1() throws Exception {
  8. Class class1 = Class.forName("com.song.reflect.Person");
  9. Constructor constructor = class1.getConstructor();
  10. Person person = (Person)constructor.newInstance(); // 相当于Person person = new Person();
  11. person.eat(); // eat...
  12. System.out.println(person); // Person{name='null', sex='null'}
  13. }
  14. @Test
  15. // 获得有参数的构造方法
  16. public void demo2() throws Exception {
  17. Class class1 = Class.forName("com.song.reflect.Person");
  18. Constructor constructor = class1.getConstructor(String.class, String.class);
  19. Person person = (Person)constructor.newInstance("张三","男"); // 相当于Person person = new Person("张三","男");
  20. // Person person = (Person)constructor.newInstance(); => 注意这样是会编译出错的,因为得到的构造方法是带参数的
  21. person.eat(); // eat...
  22. System.out.println(person); // Person{name='张三', sex='男'}
  23. }
  24. }

Field类

  • Field类代表某个类中的一个成员变量,并提供动态的访问权限
  • Field对象的而获得

得到所有的成员变量
Field[] fields = c.getFields(); // 取得所有的public属性(包括父类继承)
Fiels[] fields = c.getDeclaredFields(); // 取得所有声明的属性
得到指定的成员变量
Field name = c.getField(“name”);
Field name = c.getDeclaredField(“name”);

  • 设置Field变量是否可以访问

field.setAccessible(boolean);

  • Field变量值的读取,设置

field.get(obj)
field.set(obj,value)

  1. package com.song.reflect;
  2. import org.junit.Test;
  3. import java.lang.reflect.Field;
  4. public class FieldTest {
  5. @Test
  6. // 测试共有的属性
  7. public void demo1() throws Exception {
  8. // 获得Class
  9. Class class1 = Class.forName("com.song.reflect.Person");
  10. // 获得属性
  11. Field field = class1.getField("name");
  12. // 操作属性
  13. Person person = (Person) class1.newInstance();
  14. field.set(person, "李四");
  15. System.out.println(person); // Person{name='李四', sex='null'}
  16. }
  17. @Test
  18. // 测试私有属性
  19. public void demo2() throws Exception {
  20. // 获得Class
  21. Class class1 = Class.forName("com.song.reflect.Person");
  22. // 获得属性
  23. Field field = class1.getDeclaredField("sex");
  24. // 操作属性
  25. Person person = (Person) class1.newInstance();
  26. field.setAccessible(true); // 私有属性,需要设置一个可访问的权限
  27. field.set(person, "男");
  28. System.out.println(person); // Person{name='null', sex='男'}
  29. }
  30. }

Method类

  • Method类代表某个类中的一个成员方法
  • Method对象的获得

获得所有方法
getDeclaredMethods()
getMethods()
获得指定的方法
getDeclaredMethod(String name, Class<?>…parameterTypes)
getMethod(String name, Class<?>…parameterTypes)

  • 通过反射执行方法

invoke(Object obj, Object… args)

  1. package com.song.reflect;
  2. import org.junit.Test;
  3. import java.lang.reflect.Method;
  4. public class MethodTest {
  5. @Test
  6. // 测试共有的方法
  7. public void demo1() throws Exception {
  8. // 获得Class
  9. Class class1 = Class.forName("com.song.reflect.Person");
  10. // 获得属性
  11. Method method = class1.getMethod("eat");
  12. // 执行方法
  13. Person person = (Person) class1.newInstance();
  14. method.invoke(person); // eat...
  15. }
  16. @Test
  17. // 测试私有的方法
  18. public void demo2() throws Exception {
  19. // 获得Class
  20. Class class1 = Class.forName("com.song.reflect.Person");
  21. // 获得属性
  22. Method method = class1.getDeclaredMethod("run");
  23. // 执行方法
  24. Person person = (Person) class1.newInstance();
  25. method.setAccessible(true); // 私有方法,需要设置一个可访问的权限
  26. method.invoke(person); // eat...
  27. }
  28. @Test
  29. // 测试带参数的方法
  30. public void demo3() throws Exception {
  31. // 获得Class
  32. Class class1 = Class.forName("com.song.reflect.Person");
  33. // 获得属性
  34. Method method = class1.getDeclaredMethod("sayHello", String.class);
  35. // 执行方法
  36. Person person = (Person) class1.newInstance();
  37. method.setAccessible(true); // 私有方法,需要设置一个可访问的权限
  38. Object obj = method.invoke(person, "Song"); // eat...
  39. System.out.println(obj);
  40. }
  41. }