通过代码先感受下反射的好处

  1. // Description: 只想执行静态代码块,而不想加载其他类的其它代码块
  2. public class ReflectTest02 {
  3. // Main方法:
  4. public static void main(String[] args) {
  5. try {
  6. Class.forName("com.yxy.MyClass");
  7. } catch (ClassNotFoundException e) {
  8. e.printStackTrace();
  9. }
  10. }
  11. }
  12. class MyClass {
  13. static {
  14. System.out.println("静态代码块执行");
  15. }
  16. }

反射概念

静态语言与动态语言

1、动态语言
是一类在运行时可以改变其结构的语言:例如新的函数、对象、甚至代码可以被引进,已有的函数可以被删
除或是其他结构上的变化。通俗点说就是在运行时代码可以根据某些条件改变自身结构。
主要动态语言: Object-C、 C#、JavaScript、 PHP、 Python、 Erlang 。
2、静态语言
与动态语言相对应的,运行时结构不可变的语言就是静态语言。如Java、GoLang、C、C++

所以Java不是动态语言,但Java可以称之为“准动态语言”。即Java有一定的动态性,我们可以利用反射机制、字节码操作获得类似动态语言的特性。Java的动态性让编程的时候更加灵活!

概念

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

在编译后产生字节码文件的时候,类加载器子系统通过二进制字节流,负责从文件系统加载class文件。在执行程序(java.exe)时候,将字节码文件读入JVM中—->这个过程叫做类的加载。然后在内存中对应创建一个java.lang.Class对象—>这个对象会被放入字节码信息中,这个Class对象,就对应加载那个字节码信息,这个对象将被作为程序访问方法区中的这个类的各种数据的外部接口。
所以:我们可以通过这个对象看到类的结构,这个对象就好像是一面镜子,透过镜子看到类的各种信息,我们形象的称之为反射
这种“看透”class的能力(the ability of the program to examine itself)被称为introspection(内省、内观、反省)。Reflection和introspection是常被并提的两个术语。
说明:在运行期间,如果我们要产生某个类的对象,Java虚拟机(JVM)会检查该类型的Class对象是否已被加载。
如果没有被加载,JVM会根据类的名称找到.class文件并加载它。一旦某个类型的Class对象已被加载到内存,就可以用它来产生该类型的所有对象。
反射 - 图1
JVM执行流程

反射机制

什么是反射机制?反射机制有什么用啊?

反射机制可以让我们去操控字节码文件,通过反射机制创建对象,让程序更加灵活

反射机制相关的类在哪个包下?

实现Java反射机制的API在Java.lang.reflect包下

反射机制相关的主要的类

  • Class类(代表一个类):java.lang.Class
  • Filed类(代表类的成员变量/属性):java.lang.reflect.Filed
  • Method类(代表类的方法):java.lang.reflect.Method
  • Constructor类(代表类的构造方法):java.lang.reflect.Constructor

    获取Class类的四种方式

    1. public class ReflectTest03 {
    2. // Main方法:
    3. public static void main(String[] args) throws ClassNotFoundException {
    4. // 方式一:通过getClass()方法获取
    5. User user = new User();
    6. System.out.println(user.getClass());
    7. // 方式二:通过内置class属性
    8. System.out.println(User.class);
    9. // 方式三:用的最多:调用Class类提供的静态方法forName
    10. System.out.println(Class.forName("com.bean.User"));
    11. // 方式四:利用类的加载器
    12. ClassLoader classLoader = ReflectTest03.class.getClassLoader();
    13. System.out.println(classLoader.loadClass("com.bean.User"));
    14. }
    15. }
    16. // ++++++++++++++++++++++++++下面是User类(节省篇幅)++++++++++++++++++++++++++++
    17. public class User {
    18. public User() {
    19. System.out.println("这里是User的无参构造器");
    20. }
    21. }
    运行结果:
    image.png
    扩展:获取Class之后,可以通过无参构造器来实例化对象
    image.png

    获取Field类

    image.png
    1. // 获取类的属性名
    2. F.getName();
    3. // 获取类的属性的类型
    4. F.getType();
    5. /**
    6. * 获取类的属性的修饰符列表
    7. * 注意!!!F.getModifiers()方法返回的是int类型的数字
    8. * java.lang.reflect.Modifier包提供了相应方法: Modifer.toString(int mod)
    9. */
    10. Modifier.toString(F.getModifiers());

    获取Method类