本文主要通过代码的实现,来研究下载Java中,继承的时候,父类和子类中代码的加载顺序。

一,无继承的时候:

 首先我们先写几个类,其中类ClassA作为测试主体。

// 1,对象类,测试主体
public class ClassA {
//	public static  ClassA classa = new ClassA();
		
	static{
        System.out.println("ClassA的静态代码块A");
    }
	
	{
        System.out.println("ClassA的构造代码块A");
    }
	
    public ClassA_Public_A classA_Public_A = new ClassA_Public_A();
    
    private ClassA_Private_A classA_Private_A = new ClassA_Private_A();
    
	public static  ClassA_Static_A classA_Static_A = new ClassA_Static_A();
    
	static public void methodA(){
        System.out.println("ClassA的静态方法A");
    }
	
	
	static{
        System.out.println("ClassA的静态代码块B");
    }
	
	{
        System.out.println("ClassA的构造代码块B");
    }
    
	public ClassA_Public_B classA_Public_B = new ClassA_Public_B();
	    
    private ClassA_Private_B classA_Private_B = new ClassA_Private_B();
    
	public static  ClassA_Static_B classA_Static_B = new ClassA_Static_B();
    
	static public void methodB(){
        System.out.println("ClassA的静态方法B");
    }
    
    public ClassA(){
        System.out.println("ClassA的构造方法");
    }
    
    public void excuteOveride(){
        System.out.println("ClassA执行方法excuteOveride");
    }
}

//2,作为私有变量使用
public class ClassA_Private_A {
	
	public ClassA_Private_A(){
        System.out.println("ClassA_Private私有变量A");
    }

}

//3,作为私有变量使用
public class ClassA_Private_B {
	
	public ClassA_Private_B(){
        System.out.println("ClassA_Private私有变量B");
    }

}

//4,作为公有变量使用
public class ClassA_Public_A {
	
	public ClassA_Public_A(){
        System.out.println("ClassA_Public公有变量A");
    }

}

//5,作为公有变量使用
public class ClassA_Public_B {
	
	public ClassA_Public_B(){
        System.out.println("ClassA_Public公有变量B");
    }

}

// 6,作为静态变量使用
public class ClassA_Static_A {
	
	public ClassA_Static_A(){
        System.out.println("ClassA_Static静态变量A");
    }

}

// 7,作为静态变量使用
public class ClassA_Static_B {
	
	public ClassA_Static_B(){
        System.out.println("ClassA_Static静态变量B");
    }

}


//8,测试入口类
public class ClassTest {
	
	static {
        System.out.println("Test的静态代码块");
    }
	
	{
        System.out.println("Test构造代码块");
    }
	
	public ClassTest(){
        System.out.println("Test无参构造方法");
    }
	
    public ClassTest(String name){
        System.out.println("Test构造方法"+ name);
    }

    
    public static void main(String[] args) {
        System.out.println("ClassTest执行main方法");
        ClassA a = new ClassA();
        a.excuteOveride();
    }
    
    private static void testMethod(){
    	System.out.println("ClassTest执行testMethod方法");
    }
    
}

我们执行一下ClassTest类,执行结果如下:

--------------------------------------------------------

Test的静态代码块
ClassTest执行main方法
ClassA的静态代码块A
ClassA_Static静态变量A
ClassA的静态代码块B
ClassA_Static静态变量B
ClassA的构造代码块A
ClassA_Public公有变量A
ClassA_Private私有变量A
ClassA的构造代码块B
ClassA_Public公有变量B
ClassA_Private私有变量B
ClassA的构造方法
ClassA执行方法excuteOveride

--------------------------------------------------------

可以看到,无继承情况,在加载class时候,大原则是:

 1,先执行静态代码,

 2,其次执行普通代码,

 3,然后才是构造函数。

再细划分,每一部分都是按照代码在类中出现的顺序进行先后执行的。

 

二,有继承的时候:

我们再添加几个类,其中,ClassB作为测试主体:

// 子类ClassB,继承ClassA,测试主体
public class ClassB extends ClassA {
	
	static public void methodA(){
        System.out.println("ClassB的静态方法A");
    }
	
	static{
        System.out.println("ClassB的静态代码块A");
    }
	
	{
        System.out.println("ClassB的构造代码块A");
    }
	
	public static  ClassB_Static_A classB_Static_A = new ClassB_Static_A();
	
    private ClassB_Private_A classB_Private_A = new ClassB_Private_A();
    
    public ClassB_Public_A classB_Public_A = new ClassB_Public_A();
    
    public ClassB(){
        System.out.println("ClassB的构造方法");
    }
	
    static{
        System.out.println("ClassB的静态代码块B");
    }
	
	{
        System.out.println("ClassB的构造代码块B");
    }
	
	public static  ClassB_Static_B classB_Static_B = new ClassB_Static_B();
	
    private ClassB_Private_B classB_Private_B = new ClassB_Private_B();
    
    public ClassB_Public_B classB_Public_B = new ClassB_Public_B();
    
   
    public void excute(){
        System.out.println("ClassB执行方法excute");
    }
    
    public void excuteOveride(){
        System.out.println("ClassB执行方法excuteOveride");
    }
    
    static public void methodB(){
        System.out.println("ClassB的静态方法B");
    }
}

// 2 作为私有变量使用
public class ClassB_Private_A {
	
	public ClassB_Private_A(){
		System.out.println("ClassB_Private私有变量A");
    }

}
// 3 作为私有变量使用
public class ClassB_Private_B {
	
	public ClassB_Private_B(){
		System.out.println("ClassB_Private私有变量B");
    }

}
// 4 作为公有变量使用
public class ClassB_Public_A {
	
	public ClassB_Public_A(){
		System.out.println("ClassB_Public公有变量A");
    }

}

// 5 作为公有变量使用
public class ClassB_Public_B {
	
	public ClassB_Public_B(){
		System.out.println("ClassB_Public公有变量B");
    }

}
// 6 作为静态变量使用
public class ClassB_Static_A {
	
	public ClassB_Static_A(){
		System.out.println("ClassB_Static静态变量A");
    }

}

// 7 作为静态变量使用
public class ClassB_Static_B {
	
	public ClassB_Static_B(){
		System.out.println("ClassB_Static静态变量B");
    }

}

package com.oda.ai.controller.test;

// 8 测试入口类
public class ClassTest {
	
	static {
        System.out.println("Test的静态代码块");
    }
	
	{
        System.out.println("Test构造代码块");
    }
	
	public ClassTest(){
        System.out.println("Test无参构造方法");
    }
	
    public ClassTest(String name){
        System.out.println("Test构造方法"+ name);
    }

    
    public static void main(String[] args) {
        System.out.println("ClassTest执行main方法");
        ClassB b = new ClassB();
        b.excute();
        b.excuteOveride();
    }
    
    private static void testMethod(){
    	System.out.println("ClassTest执行testMethod方法");
    }
    
    
}

我们执行一下ClassTest类,执行结果如下:

--------------------------------------------------------

Test的静态代码块
ClassTest执行main方法
ClassA的静态代码块A
ClassA_Static静态变量A
ClassA的静态代码块B
ClassA_Static静态变量B
ClassB的静态代码块A
ClassB_Static静态变量A
ClassB的静态代码块B
ClassB_Static静态变量B
ClassA的构造代码块A
ClassA_Public公有变量A
ClassA_Private私有变量A
ClassA的构造代码块B
ClassA_Public公有变量B
ClassA_Private私有变量B
ClassA的构造方法
ClassB的构造代码块A
ClassB_Private私有变量A
ClassB_Public公有变量A
ClassB的构造代码块B
ClassB_Private私有变量B
ClassB_Public公有变量B
ClassB的构造方法
ClassB执行方法excute
ClassB执行方法excuteOveride

--------------------------------------------------------

可以看到,有继承情况,在加载class时候,大原则如下:

 1,先执行父类静态代码。

 2,其次执行子类静态代码。

 3,再次是父类普通代码。

 4,父类构造函数。

 5,之后是子类普通代码。

 6,最后子类构造函数。

同样,再细划分,每一部分都是按照代码在类中出现的顺序进行先后执行的。

同一部分中无论是变量还是代码块,都是按照代码出现在类中的先后顺序执行。

 

三,最后我们修改下测试入口类如下:

    即不创建对象实例,直接调用类的静态方法:   

//测试入口类
public class ClassTest {
	
	static {
        System.out.println("Test的静态代码块");
    }
	
	{
        System.out.println("Test构造代码块");
    }
	
	public ClassTest(){
        System.out.println("Test无参构造方法");
    }
	
    public ClassTest(String name){
        System.out.println("Test构造方法"+ name);
    }

    
    public static void main(String[] args) {

        System.out.println("ClassTest执行main方法");
        
        ClassB.methodB();
        
    }
    
    private static void testMethod(){
    	System.out.println("ClassTest执行testMethod方法");
    }
    
}

执行结果如下

--------------------------------------------------------

Test的静态代码块
ClassTest执行main方法
ClassA的静态代码块A
ClassA_Static静态变量A
ClassA的静态代码块B
ClassA_Static静态变量B
ClassB的静态代码块A
ClassB_Static静态变量A
ClassB的静态代码块B
ClassB_Static静态变量B
ClassB的静态方法B
--------------------------------------------------------

可以看到,再不创建实例的情况下,直接调用类的静态方法,

只是加载父类静态代码,和子类静态代码。