Java 如何证明加载类的动作仅发生一次。证明该类的第一个实体的创建或者对static成员的访问都有可能引起加载

  •  相关知识       

        根据《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/

猜你喜欢

转载自blog.csdn.net/u011248694/article/details/28595399
今日推荐