一、什么是反射?

1.1 Class

一个特殊的类型。

  1. public final class Class {
  2. private Class() {}
  3. }

由JVM在第一次读取到一种class类型时,将其加载进内存。每加载一种class,JVM就为其创建一个Class类型的实例,并关联起来。JVM持有的每个Class实例都指向一个数据类型(classinterface)。

1.2 反射

由于JVM为每个加载的class创建了对应的Class实例,并在实例中保存了该class的所有信息,包括类名、包名、父类、实现的接口、所有方法、字段等,因此,如果获取了某个Class实例,我们就可以通过这个Class实例获取到该实例对应的class的所有信息。

这种通过**Class**实例获取**class**信息的方法称为反射(**Reflection**)。

1.3 如何获取一个classClass实例?

  • 直接通过一个class的静态变量class获取

    1. Class cls = String.class;
  • 通过该实例变量提供的getClass()方法获取

    1. String s = "Hello";
    2. Class cls = s.getClass();

    ```java public class Hi { public static void main(String[] args) {

    1. Class cls = Person.class;
    2. System.out.println(cls.getName());
    3. for (var meth : cls.getMethods()) {
    4. System.out.println(meth);
    5. }

    } }

class Person { private String age; private String name;

  1. public void setAge(String age) {this.age = age;}
  2. public String getAge() {return age;}
  3. public void setName(String name) {this.name = name;}
  4. public String getName() {return name;}

}

// Person // public java.lang.String Person.getName() // public void Person.setName(java.lang.String) // public void Person.setAge(java.lang.String) // public java.lang.String Person.getAge() // public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException // public final void java.lang.Object.wait() throws java.lang.InterruptedException // public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException // public boolean java.lang.Object.equals(java.lang.Object) // public java.lang.String java.lang.Object.toString() // public native int java.lang.Object.hashCode() // public final native java.lang.Class java.lang.Object.getClass() // public final native void java.lang.Object.notify() // public final native void java.lang.Object.notifyAll()

  1. - 如果知道一个class的完整类名,可以通过静态方法Class.forName()获取
  2. ```java
  3. Class cls = Class.forName("java.lang.String");

1.4 动态加载

JVM在执行Java程序的时候,并不是一次性把所有用到的class全部加载到内存,而是第一次需要用到class时才加载。

二、作用

2.1 获取字段

一个实例,只要我们获取了它的Class,就可以获取它的一切信息。

  1. public class Hi {
  2. public static void main(String[] args) {
  3. Class cls = Person.class;
  4. System.out.println(cls.getName());
  5. for (var item : cls.getDeclaredFields()) {
  6. System.out.println(item);
  7. }
  8. }
  9. }
  10. class Person {
  11. private String age;
  12. private String name;
  13. public void setAge(String age) {this.age = age;}
  14. public String getAge() {return age;}
  15. public void setName(String name) {this.name = name;}
  16. public String getName() {return name;}
  17. }
  18. // Person
  19. // private java.lang.String Person.age
  20. // private java.lang.String Person.name

2.2 获取字段值

2.3 设置字段值

2.4 调用方法

参考

  1. 反射 - 廖雪峰的官方网站
  2. 访问字段 - 廖雪峰的官方网站