浅析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函数的调试,已经通过,结果如图:
经过调试,查资料,结合自己的推测和理解,似乎是明白了一些。现与大家分享讨论。
先说执行过程:
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方法来完成类的反射。根据类加载器的特殊性,结合我的调试过程,画了一个简单的流程图,
我的这幅图简单的说明了类加载器的类加载过程。先检查自己是否已经加载过该类,如果加载过,则直接返回该类,若没有则调用父类的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和网上资料,结合自己的理解,与大家分享讨论的,如果有错,欢迎大家指正,我们共同进步。
浅析Java中的反射机制原理的更多相关文章
- java中的反射机制在Android开发中的用处
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反 ...
- 浅说Java中的反射机制(二)
写过一篇Java中的反射机制,不算是写,应该是抄了,因为那是别人写的,这一篇也是别人写的,摘抄如下: 引自于Java基础--反射机制的知识点梳理,作者醉眼识朦胧.(()为我手记) 什么是反射? 正常编 ...
- 浅说Java中的反射机制(一)
在学习传智播客李勇老师的JDBC系列时,会出现反射的概念,由于又是第一次见,不免感到陌生.所以再次在博客园找到一篇文章,先记录如下: 引用自java中的反射机制,作者bingoideas.(()为我手 ...
- 【Java基础】java中的反射机制与动态代理
一.java中的反射机制 java反射的官方定义:在运行状态下,可以获取任意一个类的所有属性和方法,并且可通过某类任意一对象实例调用该类的所有方法.这种动态获取类的信息及动态调用类中方法的功能称为ja ...
- java 中利用反射机制获取和设置实体类的属性值
摘要: 在java编程中,我们经常不知道传入自己方法中的实体类中到底有哪些方法,或者,我们需要根据用户传入的不同的属性来给对象设置不同的属性值,那么,java自带的反射机制可以很方便的达到这种目的,同 ...
- Java 中的反射机制
JAVA反射机制 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法:这种动态获取的信息以及动态调用对象的方法的功能称为ja ...
- 深入理解Java中的反射机制
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意方法和属性:这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制. ...
- Java中的反射机制和动态代理
一.反射概述 反射机制指的是Java在运行时候有一种自观的能力,能够了解自身的情况为下一步做准备,其想表达的意思就是:在运行状态中,对于任意一个类,都能够获取到这个类的所有属性和方法:对于任意一个对象 ...
- Java中的反射机制Reflection
目录 什么是反射? 获取.class字节码文件对象 获取该.class字节码文件对象的详细信息 通过反射机制执行函数 反射链 反射机制是java的一个非常重要的机制,一些著名的应用框架都使用了此机制, ...
随机推荐
- JAVA GUI学习 - JTree树结构组件学习 ***
public class JTreeKnow extends JFrame { public JTreeKnow() { this.setBounds(300, 100, 400, 500); thi ...
- NSDate conversion utilities
// Gets UTC NSDate from DateTime(.Net/WCF). + (NSDate *)fromDateTime:(NSString *)dateTime { NSDate * ...
- 学习日记之模板方法模式和 Effective C++
模板方法模式: 定义:定义一个操作中的算法的骨架.而将一些步骤延伸到子类中.模板方法使得子类能够不改变算法的结构就可以重定义该算法的某些特定步骤. (1),用了继承,而且肯定这个继承有意义的情况下.就 ...
- poj 2263&& zoj1952 floyd
Fiber Network Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 2725 Accepted: 1252 Des ...
- 【转】android开发中关于模拟器emulation的常见问题
[转]android开发中关于模拟器emulation的常见问题 Trouble: 无法启动android模拟器,提示 XDM authorization key matches an existin ...
- ThinkPHP - 登录模块,核心代码
/** * 登录成功 * @return [type] [description] */ public function checkLogin($data) { $user = M($this-> ...
- [译]在 64bit 环境中执行32 bit的SSIS包
最近碰到了一个众所周知的32bit的 SSIS 包在64bit的SQL Server环境的执行问题. 我看了一些解决方案,比如修改在SSDT里面修改 debug 选项(Run64BitRuntime ...
- 通过OC实现简单的冒泡排序
NSMutableArray *arr = [@["] mutableCopy]; ; i<[arr count]-; i++) { ; j<[arr count]--i; j+ ...
- 解决centos7安装wmwaretools找不到kernel header
解决centos6安装wmwaretools找不到kernel header http://www.centoscn.com/CentosBug/softbug/2015/0525/5531.html ...
- 我常用的iphone开发学习网站[原创]
引用地址:http://www.cnblogs.com/fuleying/archive/2011/08/13/2137032.html Google 翻译 Box2d 托德的Box2D的教程! Bo ...