JAVA类加载一道笔试题

初始化

初始化这个阶段就是将静态变量(类变量)赋值的过程,即只有static修饰的才能被初始化,执行的顺序就是:父类静态域或着静态代码块,然后是子类静态域或者子类静态代码块(静态代码块先被加载,然后再是静态属性)
class A {
	static {
		System.out.print("a");//只有在类加载时候会执行一次
	}
 
	public A() {
		System.out.print("x");
	}
 
}
 
class B extends A {
	static {
		System.out.print("b");
	}
 
	public B() {
		System.out.print("y");
	}
}
 
public class Test {
 
	public static void main(String[] args) {
 
		A ab = new B();
		System.out.println();
		ab = new B();
 
	}
 
}

输出:abxy xy

执行过程:

A ab = new B();

执行时候第一使用到A、B类,JVM发现没有加载A、B的信息,故先加载,由于B继承了A类,所以会先加载A再加载B,在加载的过程中会执行static块完成类的初始化。所以会先输出ab,此时创建B对象时候,会先执行A的构造方法在执行B的构造方法,故在输出xy,所以最后输出abxy

当执行:

ab = new B();

时候发现已经加载过A、B的字节码了,故不会再加载了,所以不会输出ab,直接输出xy即可

如果代码修改为:

class A {
	static {
		System.out.print("a");// 只有在类加载时候会执行一次
	}
 
	public A() {
		System.out.print("x");
	}
 
}
 
class B extends A {
	static {
		System.out.print("b");
	}
 
	public B() {
		System.out.print("y");
	}
}
 
public class Test {
 
	public static void main(String[] args) {
 
		B ab = new B(); // 由于A ab = new B()=> B ab = new B()
		System.out.println();
		ab = new B();
	}
}

输出还是:
abxy
xy

当执行B ab = new B()时候,由于JVM事先就会知道B是继承至A的,所以需要先加载A,如果不先加载A的话,无法完成子类B的加载!所以类的加载顺序和构造器执行顺序一致,先父类再子类!

注意:容易糊涂的地方是,以为B ab =new B();以为创建B所以先加载B之后再加载A,这种理解就错误了,因为对于对象的创建是从父类开始的!

拓展:非静态代码块的执行顺序也是先父类,在子类!但是非静态代码块执行顺序在静态代码块之后,构造器之前!静态代码块只会执行一次(类加载时候执行),而非静态代码块会多在创建对象时候多次执行!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章