java继承初始化随笔

了解包括继承在内的初始化全过程,对所发生的一切有个全局性的把握,是很有益的。

//: Beetle.java
class Insect {
    private int i = 9;
    protected int j;
    Insect() {
        System.out.println("i = " + i + ",j = " + j);
        j = 39;
    }

    private static int x1 = printInit("static Insect.x1 initialized");
    static int printInit(String s) {
        System.out.println(s);
        return 47;
    }
}

public class Beetle extends Insect {
    private int k = printInit("Beetle.k initialized");
    public Beetle() {
        System.out.println("k = " + k + "\nj = " + j);
    }
    private static int x2 = printInit("static Beetle.x2 initialized");

    public static void main(String[] args) {
        System.out.println("Beetle constructor");
        Beetle beetle = new Beetle();
    }
}
output:
static Insect.x1 initialized
static Beetle.x2 initialized
Beetle constructor
i = 9,j = 0
Beetle.k initialized
k = 47
j = 39

    在Beetle上运行java时,所发生的第一件事是试图访问Beetle.main() (main是一个static方法),于是加载器开始启动并找出Beetle类的编译代码(在Beetle.class文件中)。在对它加载的过程中,编译器注意到它有一个基类,于是它继续进行加载。不管是否打算产生一个该基类的对象,这都要发生。
    验证上一句话,将对象创建代码注释后 //Beetle beetle = new Beetle();
    output:
    static Insect.x1 initialized
    static Beetle.x2 initialized
    Beetle constructor

    如果该基类还有自身的基类,那么第二个基类就会加载,如此类推。接下来,根基类的static初始化就会被执行,然后是下一个派生类,以此类推。这种方式很重要,因为派生类的static初始化可能会依赖积累成员能否被正确初始化。
    至此为止,必要的类都已经加载完毕,对象就可以创建了。首先,对象中所有的基本类型都会被设为默认值,对象引用被设为null。然后,基类的构造器就会被调用。在基类构造器完成之后,实例变量按次序被初始化。最后,构造器的其余部分被执行。


上例中main方法位于Beetle中,接下来测试另一种情况:
//: Test.java
class Insect {
    private int i = 9;
    protected int j;
    Insect() {
        System.out.println("i = " + i + ",j = " + j);
        j = 39;
    }

    private static int x1 = printInit("static Insect.x1 initialized");
    static int printInit(String s) {
        System.out.println(s);
        return 47;
    }
}

class Beetle extends Insect {
    private int k = printInit("Beetle.k initialized");
    public Beetle() {
        System.out.println("k = " + k + "\nj = " + j);
    }
    private static int x2 = printInit("static Beetle.x2 initialized");
}

public class Test {
    public static void main(String[] args) {
        System.out.println("Beetle constructor");
        Beetle beetle = new Beetle();
    }   
}
output:
Beetle constructor
static Insect.x1 initialized
static Beetle.x2 initialized
i = 9,j = 0
Beetle.k initialized
k = 47
j = 39
从此处可以发现,main方法中第一行的打印语句先执行了。
接下来把对象创建语句注释掉 //Beetle beetle = new Beetle();
output:
Beetle constructor
可以看到只有一条打印语句。此例可以帮助更清晰的了解类加载机制的第一步,对main方法的访问。

参考资料:thinking in java

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值