· [Java论坛][安全论坛][数据库论坛][操作系统论坛]
· [专题] IBM Rational高峰论坛 Windows 7十大功能
· [专题] 史上就危险7月 微软 BizSpark 计划介绍
· [IT技术周刊][IT资源下载专区][病毒求助专区]
· [热点] 我也能做CTO_赛迪连载 赛迪七夕特别行动
· [热点] Chrome 4.0采用V8引擎 Java开发编程规范

Java基础:初步探讨Java语言类加载机制

发布时间:2007.11.08 04:51     来源:赛迪网技术社区    作者:baocl

记得在刚学JAVA的时候,类的加载机制和初始化顺序经常被弄的糊里糊涂,其实当我们不太了解某些事情的时候,不防去做一做实验,让代码的运行结果说话,这或许能帮助我们更好地了解一些事情.今天我们就用一些代码来看一下类是如何被加载的,并且当有继承关系的时候,类的加载顺序又是怎么样的.

先看代码吧


/*
 * Test4.java
 *
 * Created on 2007-9-21, 9:33:31
 *
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package test1;

/**
 *
 * @author hadeslee
 */
public class Test4 {
    private void testClassForName(String name) throws ClassNotFoundException{
        Class c=Class.forName(name);
    }
    private void testNewInstance(String name) throws ClassNotFoundException, InstantiationException, IllegalAccessException{
        Class c=Class.forName(name);
        Object obj=c.newInstance();
        System.out.println(obj);
    }
    public static void main(String[] args)throws Exception {
        Test4 t=new Test4();
        t.testClassForName("test1.B");
        new B();
        new B();
    }
}
class A{
    private int aj;
    {
        aj=20;
        System.out.println("A成员初始化块");
    }
    private static int ai;
    static {
        ai=10;
        System.out.println("A静态初始化块");
    }
    public A(){
        System.out.println("A构造函数");
    }
}
class B extends A{
    private static int bi;
    static {
        bi=30;
        System.out.println("B静态初始化块");
    }
    private  int bj;
    {
        bj=40;
        System.out.println("B成员初始化块");
    }
    public B(){
        System.out.println("B构造函数");
    }
}
在代码里面我们总共有三个类,一个是做测试用的Test4,一个是A,一个是A的子类B,我们在A和B类里面都有很多输出,一个是静态初始化的输出,一个是成员初始化的输出,一个是在构造函数里面的输出,从这些输出我们可以知道代码的执行顺序,以上代码运行输出如下:

A静态初始化块
B静态初始化块
A成员初始化块
A构造函数
B成员初始化块
B构造函数
A成员初始化块
A构造函数
B成员初始化块
B构造函数

从上面我们可以看出,A和B的静态初始化块只被执行了一次,也就是类的对象将要被生成的时候,它会执行,并且执行的顺序如下:父类的静态成员,子类的静态成员,父类的成员变量和构造方法,子类的成员变量和构造方法.当再用这个类生成对象的时候,静态的部份就不再被调用了.因为静态是类的所有实例所共享的,所以它在整个虚拟机的生命周期内只执行一次.

如果我们加上一个t.testClassForName("test1.B");放在main函数的最后面,我们会发现输出还是和刚刚一样,没有任何改变,这个时候,我们知道,当我们调用Class.forName(name);的时候,类是不会自动初始化的,它默认只是把这个类的字节码读入内存,但是并没有初始化这个类.只有我们调用了newInstance()的时候,它才会被初始化.在这里我们再这样试一下:把A和B生成的class文件去掉,然后再分别调用Class.forName和new B(),看看会怎么样,我们会发现当我们调用Class.forName的时候,当我们要for的Name找不到的时候,只会抛出ClassNotFoundException,注意,它只是一个异常而已,而当我们new B()的时候,B的class文件却被我们删掉了,那就事大了,那就将抛出NoClassDefFoundError,呵呵,它就是一个Error了,这点区别我们可要注意啦,当我们在做这些事情的时候,一个只要捕获异常就可以了,一个却需要捕获一个Error,一般来说,Error级别的错误是不希望程序员去捕获的.了解了类的基本加载顺序以及加载机制后,对我们了解JAVA是有一定的帮助的.


[ 发表评论 ] 字体[  ] [ 打印 ] [ 进入博客 ] [ 进入论坛 ]  [ 推荐给朋友 ]
  相关文章
· Java基础:Java编程中异常处理的优劣之道 (11-07) · Java进阶:编写跨平台Java程序注意事项 (11-07)
· 架构与模式;Java模式设计之单例模式(四) (11-07) · 架构与模式:Java模式设计之单例模式(三) (11-07)
· 架构与模式:Java模式设计之单例模式(二) (11-07) · 架构与模式:Java模式设计之单例模式(一) (11-07)
· 对《Java与模式》中工厂方法模式的异议 (11-07) · 制作可执行的JAR文件包以及jar命令详解 (11-07)
· 用Java实现FTP服务器 (11-07) · 深入浅出--Java设计模式之迭代器模式 (11-06)
  客户需求反馈表
* 姓  名:
更多资料  了解方案  认识厂商
* 单位名称:
* 联系电话:
* 电子邮件:
资讯 通信 IT产品 IT技术 信息化
专题:谷歌发布PC操作系统Chrome OS
·芯能量 新动力 兴经济:..
·专题:英特尔与AMD和解 ..
·专题:惠普27亿收购3Com..
专题:
·专题:诺基亚危局已现 ..
·六股势力角逐4G标准 中..
·专题:联通iPhone并不贵..
 
·惠普123459黑白激打家族..
·云计算格局初现 三大阵..
·分析:虚拟化在高性能计..
2009 IBM动态架构新动力论坛
·直播:第八届中国系统与..
·专题:置身智慧海洋——..
·专题:让物品开口说话 ..