锁定老帖子 主题:Class对象与类加载器
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2009-03-25
最后修改:2009-03-31
class对象是java.lang.Class<T>这个类生成的对象, 实际上,每个类都有一个class对象。换言之,每当编写并且编译了一个新类,就会产生一个class对象(被保存在一个同名的.class文件中)。在运行时,当我们想生成这个类的对象时,运行这个程序的Java虚拟机首先检查这个类的class对象是否已经加载。如果尚未加载,JVM就会根据类名查找.class文件,并将其载入,一旦某个类的class对象被载入内存,它就被用来创建这个类的所有对象。 class类用的比较多的方法就是forName(String className) ,getName() 还有newInstance() 等等,关于他们的详细用法你可以去查查API,我在这里就不赘述。我要说的是他们的返回值,forName(String className)返回的是一个对class对象的引用,getName() 返回的是类名(也可以是接口名),而newInstance()返回的是对一个普通对象的引用。 考虑下面一段代码: public class TestStatic { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub System.out.println("用这种方式加载类:Static test = new Static()"); Static test = new Static(); System.out.println("生成test对象的class对象的类加载器是:"+test.getClass().getClassLoader()); System.out.println("生成test对象的class对象的类加载器的委托的父类加载器是:"+test.getClass().getClassLoader().getParent()); System.out.println("判定指定的 Object 是否与此 Class 所表示的对象赋值兼容:" +test.getClass().isInstance(test)); if (test instanceof Static) System.out.println("test是类Static的实例!"); System.out.println(); System.out.println("用这种方式加载类:Class.forName()"); try { Class testForName = Class.forName("Static"); Static testNew =(Static) testForName.newInstance(); System.out.println("class对象testForName的类加载器是:"+testForName.getClassLoader()); System.out.println("class对象testForName的类加载器的委托的父类加载器是:"+testForName.getClassLoader().getParent()); System.out.println("判定指定的 Object 是否与此 Class 所表示的对象赋值兼容:" +testForName.isInstance(test)); if (testNew instanceof Static) System.out.println("testNew是类Static的实例!"); System.out.println(); } catch(ClassNotFoundException e) { e.getMessage(); } catch(InstantiationException e) { e.getMessage(); } catch(IllegalAccessException e) { e.getMessage(); } System.out.println("用这种方式加载类:Static.class"); Class testClass = Static.class; System.out.println("class对象testClass的类加载器是:"+testClass.getClassLoader()); System.out.println("class对象testClass的类加载器的委托的父类加载器是:"+testClass.getClassLoader().getParent()); System.out.println("判定指定的 Object 是否与此 Class 所表示的对象赋值兼容:" +testClass.isInstance(test)); try { Static testClassNew =(Static) testClass.newInstance(); if (testClassNew instanceof Static) System.out.println("testClassNew是类Static的实例!"); } catch(InstantiationException e) { e.getMessage(); } catch(IllegalAccessException e) { e.getMessage(); } } } class Static { public Static() { System.out.println("执行构造器!"); } static { System.out.println("初始化静态变量!"); } { System.out.println("初始化非静态变量!"); } static void print() { System.out.println("为静态方法配置!"); } }
运行结果为:
代码多,但其实还是很简单的,我想表达的是: 这里有三种不同的加载类的方式,但是聪明的读者就会发现其实整个过程只有一个class对象,它产生于第一次对它的加载,也就是说,类加载器要加载一个类,它首先检查此类是否已被加载,然后再委托双亲加载器加载此类,它的双亲加载器再委托它的双亲,这样一直委托到启动加载器,启动加载器在从核心API查找此类,如果有就返回此类,否则就他的子加载器就查找此类,如果都没有就抛出ClassNotFound的异常。 第一次加载的时候初始化此类,所以我们看到在第一次加载类的时候输出了“初始化静态变量”,然后第二次用Class.ForName()加载的时候,类加载器检查到这个类已经被加载,那么就返回对这个class对象的引用,所以自始自终,虽然有不止一个的class对象的引用,但是class对象却只有一个! 如果你对加载类的顺序迷惑的话,那么就请看类加载器的一个方法吧: loadClassprotected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException
如果使用上述步骤找到类,并且 resolve 标志为真,则此方法将在得到的 Class 对象上调用 鼓励用 ClassLoader 的子类重写 ClassLoader具体加载类的顺序是: # 调用 findLoadedClass 来查看是否存在已装入的类。 所以不管用哪种方式加载类,它们实际上都执行了上面这个方法,如果这个类已经加载了,那么就返回对这个class对象的引用,然后用这个class对象可以创建实例,这个实例又可以通过getClass()得到这个class对象的引用,而这个class对象的引用又可以通过getName()得到类名,也可以通过getClassLoader()得到加载这个class对象的加载器。- -!好像我都被搞糊涂了。。呵呵 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2009-11-07
所有.java在启动jvm的时候就开始编译,推测class这个对象是static的
|
|
返回顶楼 | |
浏览 2876 次