运行状态下, 通过反射可以知道任意类的所有属性和方法,。对于任意一个实例对象, 都能调用其任意方法和属性。

1. 反射原理简单剖析:

在讲解反射之前, 我们先了解几个重要的知识点:

1.1 A a = new A() -> 做了什么事情

  1. 类加载器加载A.class文件到内存中, 执行静态代码块和静态方法
  2. 执行new语句, 并在堆中申请一片内存空间.
  3. 调用构造函数, 实例化一个对象. 并逐级调用,初始化属性值。

image.png

疑问: 子类实例化对象, 会不会实例化父类对象??

首先答案肯定是: 子类实例化对象不会实例化对象, 举个简单的例子, 如果我的父类是一个抽象类, 子类继承抽象类。如果子类实例化对象同时也实例化父类对象, 那么就与抽象类不允许实例化有冲突了。只是会调用父类的构造函数对父类属性进行初始化。

1.2 Class文件 & Class类对象:

java文件在编译后会变成class文件, 并会在项目启动的时候由类加载器加载class文件到内存中, JVM根据其字节数创建Class对象.
image.png

Class对象, 描述class文件, class文件中的构造器, 方法可以理解为组件, 对应Class对象的一个个字段。
字段、方法、构造器对象:
image.png
注解数据:
image.png
泛型信息
image.png

例子:

image.png
一个Controller字节码文件, 在加载到内存的时候, 都会被解构保存到Class类中.

1.3 类加载过程 & 类加载器:

详见 https://www.yuque.com/wangyanyang/qz7fwa/xsd243 2.2 和 2.3

2. 反射实际使用:

2.1 获得类对象(三种方式)

java.lang.Class是一个类,这个类是反射操作的源头,即:所有的反射都要从类开始进行,而最关键的是这个类有三种实例化方法, 就是获得类对象。

  1. public static void main(String[] args) {
  2. /**
  3. * 方式1: 调用Object类中的getClass()方法
  4. */
  5. ReflectTest reflectTest = new ReflectTest();
  6. Class<? extends ReflectTest> aClass = reflectTest.getClass();
  7. System.out.println(aClass);
  8. /**
  9. * 方式2: 使用“类.class”取得
  10. */
  11. Class<ReflectTest> aClass1 = ReflectTest.class;
  12. System.out.println(aClass1);
  13. /**
  14. * 方式3:
  15. * 调用Class类提供的一个方法--实例化Class对象
  16. * forName(String className)
  17. */
  18. try {
  19. Class<?> aClass2 = Class.forName("com.interview.javabasic.reflection.ReflectTest");
  20. System.out.println(aClass2);
  21. } catch (ClassNotFoundException e) {
  22. e.printStackTrace();
  23. }
  24. }

2.2 反射实例化对象

拿到Class类对象, 我们可以使用反射来实例化对象. 如下是反射实例化对象的例子

  1. public class ReflectTest2 {
  2. private Integer param;
  3. public static void main(String[] args) {
  4. ReflectTest2 reflectTest2 = new ReflectTest2();
  5. reflectTest2.normalMethod();
  6. reflectTest2.specialMethod();
  7. }
  8. public void normalMethod() {
  9. Book book = new Book();
  10. System.out.println(book.toString());
  11. }
  12. public void specialMethod() {
  13. Class<Book> bookClass = Book.class;
  14. try {
  15. Book book = bookClass.newInstance();
  16. System.out.println(book.toString());
  17. } catch (Exception e) {
  18. e.printStackTrace();
  19. }
  20. }
  21. }
  22. class Book {
  23. public Book() {
  24. System.out.println("*** Book的构造方法 ***");
  25. }
  26. @Override
  27. public String toString() {
  28. return "--- 这是Book方法 ---";
  29. }
  30. }

反射在工厂模式中的应用:

  1. public class ReflectTest3 {
  2. public static void main(String[] args) {
  3. Fruit apple = Factory.getInstance("com.interview.javabasic.reflection.Apple");
  4. apple.say("");
  5. Fruit orange = Factory.getInstance("com.interview.javabasic.reflection.Orange");
  6. orange.say("");
  7. }
  8. }
  9. interface Fruit<T> {
  10. void say(T param);
  11. }
  12. class Apple implements Fruit<String> {
  13. @Override
  14. public void say(String param) {
  15. System.out.println("i am apple");
  16. }
  17. }
  18. class Orange implements Fruit<String> {
  19. @Override
  20. public void say(String param) {
  21. System.out.println("i am orange");
  22. }
  23. }
  24. class Factory {
  25. public static Fruit getInstance(String className) {
  26. Fruit fruit = null;
  27. try {
  28. Class<?> aClass = Class.forName(className);
  29. fruit = (Fruit) aClass.newInstance();
  30. } catch (Exception e) {
  31. e.printStackTrace();
  32. }
  33. return fruit;
  34. }
  35. }

2.3. 反射调用构造方法 & 普通方法 & 成员

  1. public class ReflectTest4 {
  2. public static void main(String[] args) throws Exception {
  3. try {
  4. /**
  5. * 构造函数部分
  6. */
  7. Class<?> aClass = Class.forName("com.interview.javabasic.reflection.Phone");
  8. Constructor<?>[] constructors = aClass.getConstructors();
  9. System.out.println("获得公共的构造方法....");
  10. for (int i = 0; i < constructors.length; i++) {
  11. show(constructors[i]);
  12. }
  13. System.out.println("获取所有的构造方法...");
  14. Constructor<?>[] constructors2 = aClass.getDeclaredConstructors();
  15. for (int i = 0; i < constructors2.length; i++) {
  16. show(constructors2[i]);
  17. }
  18. System.out.println("获取多参数的, 非公共的构造函数...");
  19. Constructor<?> constructor = aClass.getDeclaredConstructor(String.class, String.class, String.class);
  20. System.out.println(constructor);
  21. System.out.println("获取无参的构造函数...");
  22. Constructor<?> constructor2 = aClass.getConstructor();
  23. System.out.println(constructor2);
  24. /**
  25. * java.lang.IllegalAccessException: Class com.interview.javabasic.reflection.ReflectTest4 can not access a member of class com.interview.javabasic.reflection.Phone with modifiers "private"
  26. */
  27. constructor.setAccessible(true);
  28. Object iphone = constructor.newInstance("iphone", "9", "699");
  29. System.out.println("实例化对象:" + iphone);
  30. System.out.println("-----------------------------------------------");
  31. /**
  32. * 获取成员变量
  33. */
  34. System.out.println("获取(public)变量...");
  35. Field[] fields = aClass.getFields();
  36. for (int i = 0; i < fields.length; i++) {
  37. show(fields[i]);
  38. }
  39. System.out.println("获取所有的变量...");
  40. Field[] allFields = aClass.getDeclaredFields();
  41. for (int i = 0; i < allFields.length; i++) {
  42. show(allFields[i]);
  43. }
  44. System.out.println("获取某一个public变量...");
  45. Field price = aClass.getDeclaredField("price");
  46. price.set(iphone, "6999");
  47. System.out.println("实例化对象:" + iphone);
  48. System.out.println("获取某一个private变量...");
  49. Field size = aClass.getDeclaredField("size");
  50. size.setAccessible(true);
  51. size.set(iphone, "15.6");
  52. System.out.println("实例化对象:" + iphone);
  53. System.out.println("-----------------------------------------------");
  54. /**
  55. * 获取成员方法
  56. */
  57. System.out.println("获取(public)方法...");
  58. Method[] methods = aClass.getMethods();
  59. for (int i = 0; i < methods.length; i++) {
  60. show(methods[i]);
  61. }
  62. System.out.println("获取所有的方法...");
  63. Method[] allMethods = aClass.getDeclaredMethods();
  64. for (int i = 0; i < allMethods.length; i++) {
  65. show(allMethods[i]);
  66. }
  67. System.out.println("获取某一个public方法...");
  68. Method price2 = aClass.getDeclaredMethod("setPrice", String.class);
  69. price2.invoke(iphone, "9999");
  70. System.out.println("实例化对象:" + iphone);
  71. System.out.println("获取某一个private方法...");
  72. Method show = aClass.getDeclaredMethod("show");
  73. show.setAccessible(true);
  74. show.invoke(iphone);
  75. } catch (Exception e) {
  76. e.printStackTrace();
  77. }
  78. }
  79. private static <T> void show(T param) {
  80. System.out.println(param);
  81. }
  82. }
  83. class Phone {
  84. String name;
  85. private String size;
  86. public String price;
  87. private Phone(String name, String size, String price) {
  88. this.name = name;
  89. this.size = size;
  90. this.price = price;
  91. }
  92. public Phone() {
  93. }
  94. @Override
  95. public String toString() {
  96. return "--- 这是Phone方法 ---" + this.name + "," + this.size + "," + this.price;
  97. }
  98. public void setPrice(String price) {
  99. this.price = price;
  100. }
  101. private void show() {
  102. System.out.println("Phone's size:" + size + ", only " + price + " RMB");
  103. }
  104. }