Java中子类、父类、变量、static方法的加载顺序

先来看一下下面这段代码,此段代码转载于:http://www.jb51.net/article/37881.htm

class Parent {
    // 静态变量
    public static String p_StaticField = "父类--静态变量";
    // 变量(其实这用对象更好能体同这一点,如专门写一个类的实例)
  
    //如果这个变量放在初始化块的后面,是会报错的,因为你根本没有被初始化
    public String p_Field = "父类--变量";
    // 静态初始化块
    static {
        System.out.println(p_StaticField);
        System.out.println("父类--静态初始化块");
    }
    // 初始化块
    {
        System.out.println(p_Field);
        System.out.println("父类--初始化块");
    }
    // 构造器
    public Parent() {
        System.out.println("父类--构造器");
    }
}
public class SubClass extends Parent {
    // 静态变量
    public static String s_StaticField = "子类--静态变量";
    // 变量
    public String s_Field = "子类--变量";
    // 静态初始化块
    static {
        System.out.println(s_StaticField);
        System.out.println("子类--静态初始化块");
    }
    // 初始化块
    {
        System.out.println(s_Field);
        System.out.println("子类--初始化块");
    }
    // 构造器
    public SubClass() {
        //super();
        System.out.println("子类--构造器");
    }
    // 程序入口
    public static void main(String[] args) {
        System.out.println("*************in main***************");
        new SubClass();
        System.out.println("*************second subClass***************");
        new SubClass();
    }
}


代码的执行结果如下:


父类--静态变量
父类--静态初始化块
子类--静态变量
子类--静态初始化块
*************in main***************
父类--变量
父类--初始化块
父类--构造器
子类--变量
子类--初始化块
子类--构造器
*************second subClass***************
父类--变量
父类--初始化块
父类--构造器
子类--变量
子类--初始化块
子类--构造器

在这段代码中,子类和父类中都有static变量和static代码块,父类中有无参的构造方法,从上面执行的结果可以得出下面结论:

1、当代码进入到子类的main方法时,此时不执行main()方法中的任何语句,这时候会先开始按顺序先加载父类的static变量、static代码块,再加载子类的static变量、static代码块;

2、当父类和子类的static变量和代码块加载完之后,开始按顺序执行main方法中的语句System.out.println("*************in main***************");;

3、执行完println语句之后,此时new一个子类对象,由于子类继承父类,此时会先按顺序初试化父类中的变量、代码块、构造方法,然后再初始化子类变量、代码块、构造方法。其中变量最先初始化创建,其次是代码块,构造方法最后创建;

4、当new完一个子类对象之后,再new第二个子类对象时,由于static变量与方法还有代码块在内存中只加载一遍,此时父类和子类已经加载了一遍,所以不会再次加载

5、当把子类main方法中的代码都删掉

		System.out.println("*************in main***************");
		new Super_Sub_Contr();
		System.out.println("*************second subClass***************");
		new Super_Sub_Contr();
此时执行程序,子类和父类的static变量和代码块也还是会加载,但是其它的变量、代码块、构造方法都不会加载。


以上代码是在子类里面直接new子类对象,如果我们新建一个类,在这个类中new子类结果会是怎样?还有,当我们初始化变量时,变量调用了一个方法,这个方法会不会在变量初始时就执行?看看下面代码执行的结果:


class Parent {
	// 静态变量
	public static String p_StaticField = "父类--静态变量";
	// 变量(其实这用对象更好能体同这一点,如专门写一个类的实例)

	// 如果这个变量放在初始化块的后面,是会报错的,因为你根本没有被初始化
	public String p_Field = "父类--变量";
	
	int a = getParent();
	// 静态初始化块
	static {
		System.out.println(p_StaticField);
		System.out.println("父类--静态初始化块");
	}
	// 初始化块

	{
		System.out.println(p_Field);
		System.out.println("父类--初始化块");
	}
	{
		System.out.println(a);
	}

	// 构造器
	public Parent() {
		System.out.println("父类--构造器");
	}

	private int getParent() {
		System.out.println("********getParent()*********");
		return 6;
	}
}

class SubClass extends Parent {
	// 静态变量
	public static String s_StaticField = "子类--静态变量";
	// 变量
	public String s_Field = "子类--变量";
	// 静态初始化块
	static {
		System.out.println(s_StaticField);
		System.out.println("子类--静态初始化块");
	}
	// 初始化块
	{
		System.out.println(s_Field);
		System.out.println("子类--初始化块");
	}

	// 构造器
	public SubClass() {
		// super();
		System.out.println("子类--构造器");
	}

}

public class Super_Sub_Contr{
	// 程序入口
	public static void main(String[] args) {
		System.out.println("*************in main***************");
		new SubClass();
		System.out.println("*************second subClass***************");
		new SubClass();
	}
}

代码执行结果


*************in main***************
父类--静态变量
父类--静态初始化块
子类--静态变量
子类--静态初始化块
********getParent()*********
父类--变量
父类--初始化块
6
父类--构造器
子类--变量
子类--初始化块
子类--构造器
*************second subClass***************
********getParent()*********
父类--变量
父类--初始化块
6
父类--构造器
子类--变量
子类--初始化块
子类--构造器

从结果可知:

1、当在另外一个类中new子类时,会先打印:*************in main***************

    这是因为在子类中new子类,此时子类还没有开始加载,所以当子类加载完后才能执行main方法;

2、当初试化变量中调用了另一个方法时,会先执行这个方法完成变量的初始化,然后再初始化代码块;


以上代码还没有涉及到子类和父类有多个构造函数,构造函数之间重载的问题,可以看看下面代码:


class Parent {
	// 静态变量
	public static String p_StaticField = "父类--静态变量";
	// 变量(其实这用对象更好能体同这一点,如专门写一个类的实例)

	// 如果这个变量放在初始化块的后面,是会报错的,因为你根本没有被初始化
	public String p_Field = "父类--变量";
	
	int a = getParent();
	// 静态初始化块
	static {
		System.out.println(p_StaticField);
		System.out.println("父类--静态初始化块");
	}
	// 初始化块

	{
		System.out.println(p_Field);
		System.out.println("父类--初始化块");
	}
	{
		System.out.println(a);
	}

	// 构造器
	public Parent() {
		this(100);
		System.out.println("父类--构造器");
	}
	
	public Parent(int i) {
		System.out.println("父类带参构造器" + "******" + i);
	}

	private int getParent() {
		System.out.println("********getParent()*********");
		return 6;
	}
}

class SubClass extends Parent {
	// 静态变量
	public static String s_StaticField = "子类--静态变量";
	// 变量
	public String s_Field = "子类--变量";
	// 静态初始化块
	static {
		System.out.println(s_StaticField);
		System.out.println("子类--静态初始化块");
	}
	// 初始化块
	{
		System.out.println(s_Field);
		System.out.println("子类--初始化块");
	}

	// 构造器
	public SubClass() {
		this(200);
		//super(300);
		System.out.println("子类--构造器");
	}
	public SubClass(int i) {
		//super(400);
		System.out.println("子类带参构造器" + "*******" + i);
	}

}

public class Super_Sub_Contr{
	// 程序入口
	public static void main(String[] args) {
		System.out.println("*************in main***************");
		new SubClass();
		System.out.println("*************second subClass***************");
		new SubClass();
	}
}

这里子类和父类都有一个无参构造函数和带参构造函数,下面分以下几种情况讨论一下:

1、初始化时,父类的无参构造函数调用this(100), 子类的无参函数调用this(200),此种情况下,子类和父类的无参构造函数和带参构造函数都会初始化;

2、父类不修改,此时将子类的带参构造函数的super(400)注释去掉,你会发现此种情况下,父类的无参构造函数没有调用,带参构造函数还是调用的;

3、父类不修改,将子类的无参构造函数的this(200)注释,改为super(300),此种情况下,子类的带参构造函数和父类的无参构造函数都没有调用;

上面部分想法借鉴了:http://blog.csdn.net/mad1989/article/details/20793539

最后,再看看下面代码的执行结果:

public class Test {

    Person person = new Person("Test");

    static{

        System.out.println("test static");

    }   

    public Test() {

        System.out.println("test constructor");

    }

     
    public static void main(String[] args) {

        new MyClass();

    }

}

class Person{

    static{

        System.out.println("person static");

    }

    public Person(String str) {

        System.out.println("person "+str);

    }

}


class MyClass extends Test {

    Person person = new Person("MyClass");

    static{

        System.out.println("myclass static");

    }

     

    public MyClass() {

        System.out.println("myclass constructor");

    }

}
test static
myclass static
person static
person Test
test constructor
person MyClass
myclass constructor




  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值