这篇文章主要介绍了Java基类和派生类中各种方法的加载顺序(常见于面试题),本文直接给出代码实例和运行结果,给后给出了加载过程总结,需要的朋友可以参考下。

先放结论,总结如下:

1. 构造类的实例对象前,先加载类本身。

2.若要加载类A,则先加载执行其父类B)的静态变量以及静态语句块(执行先后顺序按排列的先后顺序)。然后再加载执行类A的静态变量以及静态语句块。(并且对于所有的A的对象,加载A(及B)只会执行1次)

3.若需实例化类A,则先调用其父类B的构造函数,并且在调用其父类B的构造函数前,依次先调用父类B中的非静态变量及非静态语句块.最后再调用父类B中的构造函数初始化。然后再依次调用类A中的非静态变量及非静态语句块,最后调用A中的构造函数初始化。

4.而对于静态方法和非静态方法都是被动调用,即系统不会自动调用执行,所以用户没有调用时都不执行,主要区别在于静态方法可以直接用类名直接调用(实例化对象也可以),而非静态方法只能先实例化对象后才能调用。

基类静态语句块->派生类静态语句块->(若两个类都未被加载过,这个过程有且只有一次)

基类非静态语句块-基类构造函数->派生类非静态语句块->派生类构造函数->(每次构造都会出现)

被调用的(静态、非静态)方法。

追问:

先有父亲后有儿子,这句话不是只针对“构建对象”而言的吗,他也针对“类的加载”吗?我的理解是:对于构建对象的话, 的确是应该先构建父类对象,才能构建子类对象。但对于类的加载的话 ,不应该是看到内存中缺少了哪个类就应该加载哪个类的吗?

追答:

加载的时候也是一样的,当加载类A的时候,发现有父类B,就去搜索并加载B了, 这个时候还没有加载A中那些静态块,等B加载完了之后,才会返回来加载A, 也只有这样,程序才知道A中到底会有些什么方法,因为A中存在着由B继承而来的方法。 如果先加载了A,那么就会出现两种情况,一种是A中没有继承而来的方法, 另一种是加载B后再一次加载A继承而来的方法,那这样的Java就太差劲了,你说呢?

测试代码和结果:
package com.company;

public class Main{
    public static void main(String[] args){
        A a1 = new A();
        System.out.println("End of test a1 ");
        A a2 = new A();
        //a.aDisplay();
        System.out.println("End of test a2");
    }
}
class B{
    //静态变量
    static int i = 1;
    //非静态变量
    int j = 1;
    //静态语句块
    static {
        System.out.println("Base Class B:static blocks i = " + i);
    }
    //构造函数
    public B(){
        i++;
        j++;
        System.out.println("Base constructor B: "+" i = " + i + ", j = " + j);
    }
    //非静态语句块
    {
        i++;
        j++;
        System.out.println("Base Class B:non-static blocks " + "i = " + i + ", j = " + j);
    }
    //非静态方法
    public void bDisplay(){
        i++;
        System.out.println("Base Class B:static void bDisplay():	" + " i = " + i + " , j = "+j);
        return ;
    }
    //静态方法
    public static void bTest(){
        i++;
        System.out.println("Base Class B:static void bTest():	" + " i = " + i);
        return ;
    }
}

class A extends B{
    //静态变量
    static int i = 1;
    //非静态变量
    int j = 1;
    //静态语句块1
    static {
        System.out.println("Derived Class A:static blocks i = " + i);
    }
    //构造函数
    public A(){
        super();
        i++;
        j++;
        System.out.println("Derived constructor A: " + " i = " + i + " , j = " + j);
    }
    //静态语句块2
    static{
        i++;
        System.out.println("Derived Class A:static blocks i = " + i);
    }
    //非静态语句块
    {
        i++;
        j++;
        System.out.println("Derived Class A:non-static blocks" + " i = " + i + " , j = " + j);
    }
    //非静态方法
    public void aDisplay(){
        i++;
        System.out.println("Derived Class A:static void aDisplay():	"+" i = " + i + " , j = " + j);
        return ;
    }
    //静态方法
    public static void aTest(){
        i++;
        System.out.println("Derived Class A:static void aTest(): " + " i = " + i);
        return ;
    }
}

执行结果如下:(运行环境IntelliJ IDEA + jdk 1.8)

/Library/Java/JavaVirtualMachines/jdk1.8.0_161.jdk/Contents/Home/bin/java...
Base Class B:static blocks i = 1
Derived Class A:static blocks i = 1
Derived Class A:static blocks i = 2
Base Class B:non-static blocks i = 2, j = 2
Base constructor B:  i = 3, j = 3
Derived Class A:non-static blocks i = 3 , j = 2
Derived constructor A:  i = 4 , j = 3
End of test a1 
Base Class B:non-static blocks i = 4, j = 2
Base constructor B:  i = 5, j = 3
Derived Class A:non-static blocks i = 5 , j = 2
Derived constructor A:  i = 6 , j = 3
End of test a2

Process finished with exit code 0