类加载分为动态加载和静态加载。动态加载是从外存储器中加载类,一般类加载机制分析的也是动态加载。而静态加载本质上是从内存中创建类的实例对象,此时类已经被加载到内存中。
一.静态加载
通过new关键字来创建Test的实例对象。
二.动态加载
1.通过Class.forName()来加载类,然后调用类的newInstance()方法实例化对象。
2.通过类加载器的loadClass()方法来加载类,然后调用类的newInstance()方法实例化对象。
这里有几个需要比较的地方:
1.通过new关键字实例化类的对象和通过Class.forName()加载类是当前类加载器,即this.getClass.getClassLoader,只能在当前类路径或者导入的类路径下寻找类。而用指定的classLoader来加载类可以从当前路径外寻找类,这里的classLoader甚至可以用户自定义。
2.我们知道类加载机制的三个过程主要是加载-->连接-->初始化。Class.forName()实际调用的是Class.forName(className,true,this.getClass.getClassLoader),第二个参数表示加载完后是否立即初始化,第三个参数即前文提到的表示是当前类加载器。classLoader.loadClass()实际调用的是classLoader.loadClass(className,false),第二个参数表示加载完成后是否连接,即用此方法加载类,加载完成后不会去初始化,而用Class.forName()加载类加载完成后可以被初始化。所以有些类如果加载完成后需要立即被初始化则必须使用Class.forName()。例如在加载数据库驱动时,一般用Class.forName("com.mysql.jdbc.Driver")。这是因为该驱动有一个在静态代码块中注册驱动的过程,所以需要被初始化。
3.有两个异常
静态加载类时出现的一般是NoClassDefFoundError。
动态加载类时出现的一般是ClassNotFoundException。
这两者经常被用来比较,其实区别很大。NoClassDefFoundError是错误,不方便被捕捉也不需要被捕捉,不应该尝试从error中恢复程序。他是由于在使用new关键字实例化类的对象时,在内存中找不到对象了,一般比较少见,在运行时发生,即编译时可以找到类运行时却找不到了。而ClassNotFoundException是异常,是可以被捕捉的,应该捕捉并处理尝试恢复程序。这是由于利用类名动态加载类的时候,在外存储器类路径下找不到该类或者其依赖的jar包,还有一个导致其的原因是在同一个包中同一个类被不同的类加载器加载了两遍。
————————————————