java 编程中的反射机制_浅析Java中的反射机制原理

反射反射,程序员的快乐!

Java中反射机制使用的还是比较广泛的,系统的灵活性、可扩展性大都都是通过反射等方式来加载外部插件,使得系统与插件解耦的同时,增加了功能。但是很多人都只是会用,却是不知道它的实现机制,今天就由我来带大家揭开反射机制的神秘面纱。

Java中是用Class.forName(classname)来反射类。

package com.java.reflecttest;

import com.java.dbtest.DBTest;

/**

* Java反射机制测试

* @author Longxuan

*

*/

public class ReflectTest {

/**

* 测试反射类

*/

public static void refTest(){

String className = "com.java.dbtest.TestConnection";

DBTest dbTest = null;

try {

//通过反射机制,使用类装载器,装载该类

Class tc = Class.forName(className);

//输出反射得到的类

System.out.println(tc);

//创建该类的实例,转化为接口

dbTest =(DBTest)tc.newInstance();

//通过接口,调用该类的方法

dbTest.SelectUser();

} catch (ClassNotFoundException e) {

e.printStackTrace();

} catch (InstantiationException e) {

e.printStackTrace();

} catch (IllegalAccessException e) {

e.printStackTrace();

}

}

public static void main(String[] args){

refTest();

}

}

通过main函数的调试,已经通过,结果如图:

8e87170a23251c3b78519adba68ecd88.png       

3bb8bb9d3bcdece136a230ef4d18dc31.png

经过调试,查资料,结合自己的推测和理解,似乎是明白了一些。现与大家分享讨论。

先说执行过程:

Class.forName(classname)方法,实际上是调用了Class类中的 Class.forName(classname, true, currentLoader)方法。参数:name - 所需类的完全限定名;initialize - 是否必须初始化类;loader - 用于加载类的类加载器。currentLoader则是通过调用ClassLoader.getCallerClassLoader()获取当前类加载器的。类要想使用,必须用类加载器加载,所以需要加载器。反射机制,不是每次都去重新反射,而是提供了cache,每次都会需要类加载器去自己的cache中查找,如果可以查到,则直接返回该类。

有意思的是java的类加载器也有些门道。它分为BootStrap Class Loader(引导类加载器),Extensions Class Loader (扩展类加载器),App ClassLoader(或System Class Loader),当然少不了Custom ClassLoader(用户自定义类加载器)。其加载过程中会先检查类是否被已加载,检查顺序是自底向上,从Custom ClassLoader到BootStrap ClassLoader逐层检查,只要某个classloader已加载就视为已加载此类,保证此类只所有ClassLoader加载一次。而加载的顺序是自顶向下,也就是由上层来逐层尝试加载此类。类加载器的详细介绍会在接下来的博文中较深入的分析,欢迎期待。

在forName方法中,调用了ClassLoader.loadClass方法来完成类的反射。根据类加载器的特殊性,结合我的调试过程,画了一个简单的流程图,

5f893cc02418fe7b95eaba561e57d57b.png

我的这幅图简单的说明了类加载器的类加载过程。先检查自己是否已经加载过该类,如果加载过,则直接返回该类,若没有则调用父类的loadClass方法,如果父类中没有,则执行findClass方法去尝试加载此类,也就是我们通常所理解的片面的"反射"了。这个过程主要通过ClassLoader.defineClass方法来完成。defineClass 方法将一个字节数组转换为 Class 类的实例(任何类的对象都是Class类的对象)。这种新定义的类的实例需要使用 Class.newInstance 来创建,而不能使用new来实例化。

为什么说“任何类的对象都是Class类的对象”呢?在Java中,每个class都有一个相应的Class对象。也就是说,当我们编写一个类(.java文件),编译完成后,在生成的.class文件中,就会产生一个Class对象,用于表示这个类的类型信息。

其实说的简单通俗一点,就是在运行期间,如果我们要产生某个类的对象,Java虚拟机(JVM)会检查该类型的Class对象是否已被加载。如果没有被加载,JVM会根据类的名称找到.class文件并加载它。一旦某个类型的Class对象已被加载到内存,就可以用它来产生该类型的所有对象。

以上内容是我经过调试、查java Api和网上资料,结合自己的理解,与大家分享讨论的,如果有错,欢迎大家指正,我们共同进步。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值