一道面试题梳理类加载,多态,继承等问题

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,这种理解就错误了,因为对于对象的创建是从父类开始的!

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

实践代码:

class A {
	static {
		System.out.print("a");// 只有在类加载时候会执行一次
	}
 
	{
		System.out.print("a-a");
	}
 
	public A() {
		System.out.print("x");
	}
 
}
 
class B extends A {
	static {
		System.out.print("b");
	}
	{
		System.out.print("b-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();
	}
}

输出:

aba-axb-by
a-axb-by

如果两个类没有继承关系的话,类的加载顺序就是按照代码的执行顺序进行加载的。


class C {
	static {
		System.out.print("c");
	}
 
	public C() {
		System.out.print("x");
	}
 
}
 
 
class D {
	static {
		System.out.print("d");
	}
 
	public D() {
		System.out.print("y");
	}
 
}
 
 
public class Test1 {
	
	public static void main(String[] args) {
		
		C c=new C();
		System.out.println();
		D d=new D();
		
		
	}
 
}

输出:

cx
dy

猜你喜欢

转载自blog.csdn.net/qq_41582642/article/details/81234448