反射的简单理解

前言

反射: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的几种方式

  1. 如果在编写代码时, 知道类的名称, 且类已经存在, 可以通过
    包名.类名.class 得到一个类的 类对象
  2. 如果拥有类的对象, 可以通过
    Class 对象.getClass() 得到一个类的 类对象
  3. 如果在编写代码时, 知道类的名称 , 可以通过
    Class.forName(包名+类名): 得到一个类的 类对象
    上述的三种方式, 在调用时, 如果类在内存中不存在, 则会加载到内存 ! 如果类已经在内存中存在, 不会重复加载, 而是重复利用 !

//获取Constructor

通过class对象 获取一个类的构造方法

  1. 通过指定的参数类型, 获取指定的单个构造方法
    getConstructor(参数类型的class对象数组)
    例如:
    构造方法如下: Person(String name,int age)
    得到这个构造方法的代码如下:
    Constructor c = p.getClass().getConstructor(String.class,int.class);
  2. 获取构造方法数组
    getConstructors();
  3. 获取所有权限的单个构造方法
    getDeclaredConstructor(参数类型的class对象数组)
  4. 获取所有权限的构造方法数组
    getDeclaredConstructors();

//获取Method

通过class对象 获取一个类的方法

  1. getMethod(String methodName , class… clss)
    根据参数列表的类型和方法名, 得到一个方法(public修饰的)
  2. getMethods();
    得到一个类的所有方法 (public修饰的)
  3. getDeclaredMethod(String methodName , class… clss)
    根据参数列表的类型和方法名, 得到一个方法(除继承以外所有的:包含私有, 共有, 保护, 默认)
  4. getDeclaredMethods();
    得到一个类的所有方法 (除继承以外所有的:包含私有, 共有, 保护, 默认)

//获取Field

通过class对象 获取一个类的属性

  1. getDeclaredField(String filedName)
    根据属性的名称, 获取一个属性对象 (所有属性)
  2. getDeclaredFields()
    获取所有属性
  3. getField(String filedName)
    根据属性的名称, 获取一个属性对象 (public属性)
  4. getFields()
    获取所有属性 (public)

总结

有反必有正,就像世间的阴和阳,计算机的0和1一样。天道有轮回,苍天…
//后续学习框架时再深入理解