反射的简单理解
前言
反射:JAVA的高级特性之一,难度感觉很大,刚学习时没有合适的应用场景,后续学习框架时 再深入了解,下面记录一些反射的规则用法。根据百度百科的定义,反射主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(是一种能力???)。目前我理解的是:反射就是一种反向功能,就是从类或对象中推导出Class类,然后再从Class类中获得类的信息。和正向过程正好相反,正向过程为:设计一个类,类实例化成对象,对象调方法或属性去实现一些功能。反射编程时在编译时并不确定是哪个类被加载了,只有"**运行以后"**这个类才被加载。而正向编程,代码编译之后,就可以确定是哪个类了,程序启动之后代码运行之前,类就已经被JVM加载了。
(了解)反射机制是构建框架技术的基础所在,使用反射可以避免将代码写死在框架中。
以下列举一些反射的结构
一、类加载器
JAVA类加载器是JAVA运行时得环境的一部分,负责动态加载JAVA类到JAVA虚拟机中。
java默认有三种类加载器,BootstrapClassLoader、ExtensionClassLoader、App
ClassLoader。
BootstrapClassLoader(引导启动类加载器):
嵌在JVM内核中的加载器,该加载器是用C++语言写的,主要负载加载JAVA_HOME/lib下的类库,引
导启动类加载器无法被应用程序直接使用。
ExtensionClassLoader(扩展类加载器):
ExtensionClassLoader是用JAVA编写,且它的父类加载器是Bootstrap。
是由sun.misc.Launcher$ExtClassLoader实现的,主要加载JAVA_HOME/lib/ext目录中的类
库。
它的父加载器是BootstrapClassLoader
App ClassLoader(应用类加载器):
App ClassLoader是应用程序类加载器,负责加载应用程序classpath目录下的所有jar和class文
件。它的父加载器为Ext ClassLoader。
代码如下(示例):
//类通常是按需加载,即第一次使用该类时才加载,由于有了类加载器,java运行时系统不需要知道文件与文件系统。
//委派概念:如果一个类加载器收到了一个类加载请求,他不会自己去尝试加载这个类,而是把这个请求转交给父类加载器去完成。每一个层次的类加载器都是如此。因此所有的类加载请求都应该传递到最顶层的启动类加载器中,只有到父类加载器反馈自己无法完成这个加载请求(在他的搜索范围没有找到这个类)时,子类加载器才会尝试自己去加载。委派的好处就是避免有些类被重复加载。
二、Class对象
在java中,每一个字节码文件,被加载到内存后,都存在一个对应的class类型的对象。
//得到Class的几种方式
- 如果在编写代码时, 知道类的名称, 且类已经存在, 可以通过
包名.类名.class 得到一个类的 类对象 - 如果拥有类的对象, 可以通过
Class 对象.getClass() 得到一个类的 类对象 - 如果在编写代码时, 知道类的名称 , 可以通过
Class.forName(包名+类名): 得到一个类的 类对象
上述的三种方式, 在调用时, 如果类在内存中不存在, 则会加载到内存 ! 如果类已经在内存中存在, 不会重复加载, 而是重复利用 !
//获取Constructor
通过class对象 获取一个类的构造方法
- 通过指定的参数类型, 获取指定的单个构造方法
getConstructor(参数类型的class对象数组)
例如:
构造方法如下: Person(String name,int age)
得到这个构造方法的代码如下:
Constructor c = p.getClass().getConstructor(String.class,int.class); - 获取构造方法数组
getConstructors(); - 获取所有权限的单个构造方法
getDeclaredConstructor(参数类型的class对象数组) - 获取所有权限的构造方法数组
getDeclaredConstructors();
//获取Method
通过class对象 获取一个类的方法
- getMethod(String methodName , class… clss)
根据参数列表的类型和方法名, 得到一个方法(public修饰的) - getMethods();
得到一个类的所有方法 (public修饰的) - getDeclaredMethod(String methodName , class… clss)
根据参数列表的类型和方法名, 得到一个方法(除继承以外所有的:包含私有, 共有, 保护, 默认) - getDeclaredMethods();
得到一个类的所有方法 (除继承以外所有的:包含私有, 共有, 保护, 默认)
//获取Field
通过class对象 获取一个类的属性
- getDeclaredField(String filedName)
根据属性的名称, 获取一个属性对象 (所有属性) - getDeclaredFields()
获取所有属性 - getField(String filedName)
根据属性的名称, 获取一个属性对象 (public属性) - getFields()
获取所有属性 (public)
总结
有反必有正,就像世间的阴和阳,计算机的0和1一样。天道有轮回,苍天…
//后续学习框架时再深入理解