• 反射机制(Reflection)允许程序在执行期间借助 Reflection API 取得任何类的内部信息,并能直接操作任意对象的内部属性以及方法
  • 加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个 Class 对象),这个对象就包含了完整的类的结构信息,我们可以通过这个对象看到类的结构。

反射相关 API:

  • java.lang.Class
  • java.lang.reflect.Method:方法
  • java.lang.reflect.Field:属性
  • java.lang.reflect.Constructor:构造器
  • ……

1 获取 Class 反射对象

image.png

  1. package com.lht.reflection;
  2. public class TestReflection {
  3. public static void main(String[] args) throws ClassNotFoundException {
  4. // 输出 class com.lht.reflection.User
  5. Class c1 = Class.forName("com.lht.reflection.User");
  6. System.out.println(c1);
  7. }
  8. }
  9. // 实体类
  10. class User {
  11. private String name;
  12. private int id;
  13. public User() {
  14. }
  15. public User(String name, int id) {
  16. this.name = name;
  17. this.id = id;
  18. }
  19. public String getName() {
  20. return name;
  21. }
  22. public void setName(String name) {
  23. this.name = name;
  24. }
  25. public int getId() {
  26. return id;
  27. }
  28. public void setId(int id) {
  29. this.id = id;
  30. }
  31. @Override
  32. public String toString() {
  33. return "com.lht.reflection.User{" +
  34. "name='" + name + '\'' +
  35. ", id=" + id +
  36. '}';
  37. }
  38. }

Class 对象有很多方法:

  • getAnnotation() 获取注解
  • newInstance() new 一个该类对象
  • getMethods() 获取该类的方法
  • ……

一个类只有一个 Class 对象,可以通过打印 hash code 来验证:

  1. Class c1 = Class.forName("com.lht.reflection.User");
  2. Class c2 = Class.forName("com.lht.reflection.User");
  3. Class c3 = Class.forName("com.lht.reflection.User");
  4. System.out.println(c1.hashCode());
  5. System.out.println(c2.hashCode());
  6. System.out.println(c3.hashCode());

可以发现它们的 hash code 是相同的。

在 Object 类中定义了public final Class getClass()方法,此方法被所有子类继承,并且与Class.forName()获得的 Class 对象是同一个。

2 得到 Class 类的几种方式

  1. 通过类的静态属性**class**获取。该方法最为安全可靠,程序性能最高

Class clazz = Person.class;

  1. 通过某个类实例的**getClass()**方法获取

Class clazz = person.getClass();

  1. 通过包名 + 类名(全类名)使用 Class 类的静态方法**forName()**获取,可能抛出**ClassNotFoundException**

Class clazz = Class.forName("com.lht.Reflection.User");

  1. 内置基本类型的包装类可以直接使用【类名.Type】
  2. 利用 ClassLoader