为什么需要Java反射

为何需要反射,java为何能够跨平台,就是因为JVM(Java虚拟机)

下图是Java内存模型,

为什么需要Java反射_第1张图片

假如你写了一段代码:

public class Main {
    public static void main(String[] args) {
        Object o=new Object();
    }
}

运行起来,

  1. 代码编译为->.class文件
  2. 类加载器将.class 文件加载进内存中

其中,

  1. 类Object加载到方法区
  2. 创建了Object类的class对象在堆中。

class对象:不是new出来的对象o,而是类的类型对象,每个类只有一个class对象,作为方法区类的数据结构的接口。jvm创建对象前,会先检查类是否加载,寻找类对应的class对象,若加载好,则为你的对象分配内存,初始化也就是代码:new Object()。

方法区存的是类的信息,不是存类对象的

类加载器加载类是通过方法区上类的信息在堆上创建一个类的Class对象,这个Class对象是唯一的,由JVM保证唯一,之后对这个类的创建都是根据这个Class对象来操作的

你可以理解成类存在方法区中,类的class对象存在于堆中,这个class对象会作为运行时创建该类对象的模版。这个class对象是唯一对应该类的,要区分所谓的实例和class对象。为什么需要class对象,你想下如果一个加载进方法区的类,在jvm运行时是动态加载进来的,没有这个class对象你思考该如何访问一个未知的类并创建对象呢?没错就是这个class作为访问接口。

上面的流程就是自己写好的代码扔给jvm去跑,跑完就完事了,jvm关闭,你的程序也停止了。

为什么要讲这个呢?因为要理解反射必须知道它在什么场景下使用。

上面的程序对象是自己new的,程序相当于写死了给jvm去跑。假如一个服务器上突然遇到某个请求要用到某个类但没加载进jvm,是不是要停下来自己写段代码,new一下,启动一下服务器

反射是什么呢?当我们的程序在运行时,需要动态的加载一些类,这些类可能之前用不到所以不用加载到jvm,而是在运行时根据需要才加载,这样的好处对于服务器来说不言而喻。

举个例子

1. 加载数据库驱动

我们的项目底层数据库有时使用mysql,有时用oracle,需要动态地根据实际情况加载驱动类,这个时候反射就有用了,假设 com.java.dbtest.myqlConnection,com.java.dbtest.oracleConnection这两个类我们要用,这时候我们的程序就写得比较动态化,

通过Class tc = Class.forName("com.java.dbtest.TestConnection"),

通过类的全类名让jvm在服务器中找到并加载这个类,而如果是oracle则传入的参数就变成另一个了。这时候就可以看到反射的好处了,这个动态性就体现出java的特性了!

2. spring的bean

spring中,当你配置各种各样的bean时,是以配置文件的形式配置的,你需要用到哪些bean就配哪些,spring容器就会根据你的需求去动态加载,你的程序就能健壮地运行。

java的反射机制就是增加程序的灵活性,避免将程序写死到代码里 

例如:

不使用反射:实例化一个 person()对象,new person(); 如果想变成 实例化 其他类, 那么必须修改源代码,并重新编译。

使用反射: class.forName("person").newInstance(); 而且这个类描述可以写到配置文件中,如 **.xml, 这样如果想实例化其他类,只要修改配置文件的"类描述"就可以了,不需要重新修改代码并编译。

那么什么是Java的反射呢?

       Java程序能够运行,那么就得让Java类要被Java虚拟机加载。Java类如果不被Java虚拟机加载,是不能正常运行的。现在我们运行的所有的程序都是在编译期的时候就已经知道了你所需要的那个类的已经被加载了。

Java的反射机制是在编译并不确定是哪个类被加载了,而是在程序运行的时候才加载、探知、自审。使用在编译期并不知道的类。这样的特点就是反射。

你可能感兴趣的:(为什么需要Java反射)