类的加载机制和反射总结

来源:互联网 发布:淘宝店铺装修需要多久 编辑:程序博客网 时间:2024/06/05 09:37

本系列文章由@liuchyi出品,转载请注明出处。  

文章链接: http://blog.csdn.net/liuchyi/article/details/28419949


      java.lang.reflect包下有Class,Method,Field,Constructor和Array等类,这些类分别代表了类、方法
Field、构造器和数据。Java程序可以通过使用这些类动态地获取某个对象、某个类的运行时的信息,
并可以动态地创建Java对象、动态地调用Java方法,动态访问和修改Field。

tips:
1.JVM进程结束,该进程在内存中的状态将会丢失,两次运行Java程序处于不同的JVM进程中,数据不共享。
2.类加载器之间的父子关系并不是类继承上的父子关系,这里的父子关系是类加载器实例之间的关系。
3.系统类加载器的加载路径是程序运行的当前路径,扩展类的加载器的加载路径是%JAVA%/jre/lib/ext
4.系统类加载器是AppClassLoader的实例,扩展类加载器是ExtClassLoader的实例,两者都是URLClassLoader的实      例。
5.要实现自定义的类加载器可以通过集成ClassLoader这类并重写loadClass(String name,boolean resolve)
   或者findClass(String name),建议重写后者,因为可以避免覆盖默认类加载器的父类委托、缓冲机制两种策略。
6.ClassLoader的核心方法defineClass(String name,byte[] b,int off,int len),该方法负责将指定类的字节码文件
   即.class文件读入字节组byte[] b内,并把它转换为Class对象,该字节码文件可以来源于文件、网络等。
7.类的初始化时,系统会保证该类以及所有父类(包括直接父类和间接父类)都被初始化。
8.当某个静态Field使用final修饰,而且它的值可以在编译时就确定下来的,那么其他地方使用该静态Field时,实际
   上并没有使用该静态Field,而是想当于使用了常量,也就是说该类不会被初始化。假如是动态会确定的Field,则
   该类时会被初始化的。
9.JAVA程序中许多对象在运行时都会出现两种状态:编译时类型和运行时类型,如Person p=new Student(),编译
   时P是Person类型,运行时Student类型。

类的加载步骤:

1.加载:将类的class文件读入内存,并为之创建一个java.lang.Class对象,系统中所有的类都是Class的实例。
类加载器有:Bootstrap ClassLoader--Extension ClassLoader--System ClassLoader--User ClassLoader
Bootstrap ClassLoader不是java.lang.ClassLoader的子类(其他三个都是),而是由JVM自身实现的,所以
BootstrapClassLoader NOT Extension ClassLoader parent.它负责加载Java的核心类。
类加载机制:
1.全盘负责:当一个类加载器负责加载某一个类时,该类所依赖的和引用的其他类也将由该类加载器负责载入
2.父类委托:让parent类加载器试图加载该Class,只有在父类加载器无法加载该类时才尝试从自己的类路径
中加载该类。
3.缓存机制:缓存机制将会保证所有加载过的Class都会被缓存,当程序需要使用某个Class时,类加载器先从

缓存去中搜寻,但找不到该Class时才会读入对应二进制数据,并将其转换为Class对象,这就是为啥修改了               Class后必须重新启动JVM,修改结果才会生效原因。

2.连接:当类被加载之后,系统为之生成一个对象的Class对象,接着将会进入连接阶段,连接阶段负责把类的二进制数据合并到JRE中,类连接可以分为如下3个阶段:
1.验证:验证阶段用于检验被加载的类是否有正确的内部结构、并和其他类协调一致。
2.准备:类准备阶段则负责为类的静态Field分配内存、并设置默认初始值。

3.解析:将类的二进制数据中符号引用替换成直接引用。

3.类的初始化:JVM负责对类进行初始化,一般有如下步骤
1.假如这个类还没有被加载和连接,则程序先加载并连接该类。
2.假如该类的直接父类还没有被初始化,则先初始化其直接父类。
3.假如类中有初始化语句,则系统依次执行这些初始化语句。

自定义类加载器的功能:
1.执行代码前自动验证数字签名;
2.根据用户提供密码解密代码,实现代码混淆器来避免反编译Class文件;
3.根据用户需求俩动态加载类;
4.根据应用需求把其他数据以字节码的形式加载带其他应用中。

为了获取程序运行时对象和类的真实信息,可以有两种做法:
1.假如编译和运行时都完全知道了类型的具体信息,则可以通过instanceof运算符来进行判断。
2.假如编译时无法预知对象和类的属性,则可以通过运行时的信息来发现对象和类的信息,也就是通过反射。

反射一般步骤:
1.获取Class对象:使用Class类静态方法forName(String clazzName)或者某对象.getClass()方法
   又或者通过person.class来获取Class对象。推荐.class方法,安全,程序性能更好。
2.Class类提供大量实例方法类获取该Class对象所对应类的详细信息,具体有构造器、Method、Annotation、
   Parent、修饰符、所在包、类名、Field等.
   步骤也就是:获取Class对象--通过构造器创建该类对象--Method调用方法--getField()/setField访问属性值。
0 0
原创粉丝点击