欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

java中类的加载与实例化顺序

程序员文章站 2022-07-10 10:47:08
...
首先来看一段程序,通过它的输出来分析类的加载以及实例化的机制。
public class T  implements Cloneable {
	public static int k = 0;
	public static T t1 = new T("t1");
	public static T t2 = new T("t2");
	public static int i = print("i");
	public static int n = 99;

	public int j = print("j");
	
	{
		print("构造块");
	}

	static {
		print("静态块");
	}

	public T(String str) {
		System.out.println((++k) + ":" + str + "    i=" + i + "  n=" + n);
		++n;
		++i;
	}

	public static int print(String str) {
		System.out.println((++k) + ":" + str + "   i=" + i + "   n=" + n);
		++n;
		return ++i;
	}
	
	public static void main(String[] args) {
		
	}
}

输出:
1:j   i=0   n=0
2:构造块   i=1   n=1
3:t1    i=2  n=2
4:j   i=3   n=3
5:构造块   i=4   n=4
6:t2    i=5  n=5
7:i   i=6   n=6
8:静态块   i=7   n=99

首先从main函数进入程序,类中的静态成员会被先加载,加载的时候,JVM首先将类中静态属性的声明和静态方法的声明加载到内存中(方法区中),然后将静态属性赋值,之后执行静态块中的代码。如果在类加载的时候遇到实例化的情况,首先加载普通属性的声明,然后普通方法的声明,之后是普通属性赋值,执行构造块代码,最后执行构造函数中的代码。如果有继承关系,父类优先于子类。这是基本的加载顺序。
接下来我们逐行来分析。首先加载类中的静态属性声明,(static )int k, T t1, T t2, int i, int n,(只有声明还没有赋值),然后加载静态方法声明static int print(String str) {}。之后对静态属性赋值,首先加载k = 1;当加载到t1 = new T("t1")时,这是实例化的过程,这时类暂时不加载。按照上面所说的,实例化的时候首先加载类中的普通成员声明 int j, 然后是普通方法声明,public T(String str){},之后对普通属性赋值,这时j = print("j"), 就调用了public static int print(String str){} 方法,这时的i和n还没有被赋值,仅仅是JVM在声明时给它分配的初始值,都为0。因此这时的输出为1:j   i=0   n=0。这是普通属性的赋值,接下来是构造块的执行因此有了第二行输出:2:构造块   i=1   n=1,最后是构造函数执行,有了第三行输出:3:t1    i=2  n=2。到现在t1的实例化过程结束,接着进行类的加载。 接下来对t2进行复制,也是一个实例化的过程,和上面蓝色字体描述的一样, 于是就有了4,5,6三行输出。再下面对static int i进行复制 i = print("i") 因此有了第七行输出。接下来对public static n 进行赋值, n = 99。此时静态属性赋值全部结束,最后加载静态块中的内容,print("静态块"), 因为这时的n已经被赋值了,因此最后的输出为:8:静态块   i=7   n=99