- 相关知识
根据《Java编程思想》中的介绍,类是在其任何static成员被访问时加载的。构造器也是static方法,只是static关键字没有显示地写出来。
和C语言程序一样,Java应用程序的入口函数也是main,由于JVM在运行这个Java应用程序的时候,首先会调用main方法,调用时不实例化这个类的对象,而是通过类名直接调用因此需要是限制为public static。对于Java中的main方法,JVM有限制,不能有返回值,因此返回值类型为void。
在类的内部,变量的定义在任何方法(包括构造器)被调用之前得到初始化。
import static my.tool.Print.*;
class A {
static int j = printInit("A.j initialized");
static int printInit(String s) {
print(s);
return 1;
}
A() {
print("A() constructor");
}
public String toString() {
return "print A";
}
}
class B extends A {
static int k = printInit("B.k initialized");
B() {
print("B() constructor");
}
}
class C {
static int n = printInitC("C.n initialized");
static A a = new A();
static int printInitC(String s) {
print(s);
return 1;
}
}
class D {
D() {
print("D() constructor");
}
}
public class Demo extends B {
static int i = printInit("Demo.i initialized");
Demo() {
print("Demo() constructor");
}
public static void main(String[] args) {
print("hi");
print(C.a);
D d = new D();
}
}
Java程序的每个文件中,每一个类会生成一个class文件。上面的程序生成的文件如下所
示,
然后在需要类的时候进行加载,先看看上面程序的运行结果:
过程:JVM首先找到应用程序的入口函数main,又因为Demo类是从B类继承过来的,就加载B类,然后B又是从A继承过来的,接着加载A类。A没有基类于是A类中的static初始化被执行,然后是导出类,以此往下执行。接着执行main函数中的第一行,打印出"hi"字符串。然后是打印C类中的静态成员a,引起加载C类,执行static初始化,这里新建了一个A类对象所以调用A类的构造器。最后是新建一个D类的对象,加载D类,调用D类的构造器。
个人理解总结(望指正):从C类中的静态A类对象可以看出,这个时候要创建一个A类的对象,但是这里只显示调用了A类的构造函数,所以我们可以知道加载类的动作只执行了一次。刚开始Demo、A、B类的加载说明了对static成员的访问会引起加载,然后D类对象的创建说明了该类的第一个实体的创建会引起加载。
参考资料:http://lavasoft.blog.51cto.com/62575/53263/