先来看看一段Java代码:
package example; class Print { public Print(String info) { System.out.println("测试信息----" + info); } } class BaseA { private Print p = new Print("实例变量A"); private static Print p1 = new Print("静态变量A"); static { System.out.println("BaseA静态块"); } public BaseA() { System.out.println("BaseA构造方法"); } public void Invoke() { System.out.append("Invoke----BaseA"); } } class BaseB extends BaseA { private Print p = new Print("实例变量B"); private static Print p1 = new Print("静态变量B"); static { System.out.println("BaseB静态块"); } public BaseB() { System.out.println("BaseB构造方法"); } @Override public void Invoke() { System.out.append("Invoke----BaseB"); } } class BaseC extends BaseB { private Print p = new Print("实例变量C"); private static Print p1 = new Print("静态变量C"); static { System.out.println("BaseC静态块"); } public BaseC() { System.out.println("BaseC构造方法"); } @Override public void Invoke() { System.out.append("Invoke----BaseC"); } } public class Test { public static void main(String[] args) { BaseC bc = new BaseC(); bc.Invoke(); } } run: 测试信息----静态变量A BaseA静态块 测试信息----静态变量B BaseB静态块 测试信息----静态变量C BaseC静态块 测试信息----实例变量A BaseA构造方法 测试信息----实例变量B BaseB构造方法 测试信息----实例变量C BaseC构造方法 Invoke----BaseC成功构建 (总时间: 0 秒)
由此可见:Java在实例化对象的时候有几个规律
1、静态的肯定在前面:静态变量>静态块代码
2、总是从最底层的类开始实例化,从父类开始把所有静态的加载完,然后从父类开始把所有实例的东东加载完
执行顺序:
1. 初始化ParentClass的静态字段(按声明顺序)
2. 初始化ParentClass的静态块
3. 初始化ChildClass的静态字段(按声明顺序)
4. 初始化ChildClass的静态块
5. 初始化ParentClass的实例字段(按声明顺序)
6. 初始化ParentClass的构造方法
7. 初始化ChildClass的实例字段(按声明顺序)
8. 初始化ChildClass的构造方法
再来看看C#的代码:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication1 { class Print { public Print(string info) { Console.WriteLine("测试信息---" + info); } } class BaseA { private Print p = new Print("实例变量A"); private static Print p1 = new Print("静态变量A"); static BaseA() { Console.WriteLine("静态构造方法A"); } public BaseA() { Console.WriteLine("构造方法A"); } public virtual void Invoke() { Console.WriteLine("Invoke---BaseA"); } } class BaseB : BaseA { private Print p = new Print("实例变量B"); private static Print p1 = new Print("静态变量B"); static BaseB() { Console.WriteLine("静态构造方法B"); } public BaseB() { Console.WriteLine("构造方法B"); } public override void Invoke() { Console.WriteLine("Invoke---BaseB"); } } class BaseC : BaseB { private Print p = new Print("实例变量C"); private static Print p1 = new Print("静态变量C"); static BaseC() { Console.WriteLine("静态构造方法C"); } public BaseC() { Console.WriteLine("构造方法C"); } public new void Invoke() { Console.WriteLine("Invoke---BaseC"); } } class Program { static void Main(string[] args) { BaseC bc = new BaseC(); bc.Invoke(); } } } 测试信息---静态变量C 静态构造方法C 测试信息---实例变量C 测试信息---静态变量B 静态构造方法B 测试信息---实例变量B 测试信息---静态变量A 静态构造方法A 测试信息---实例变量A 构造方法A 构造方法B 构造方法C Invoke---BaseC
1、先静态的东东在前面,静态变量>静态构造方法
2、从子类到父类(非静态构造方法除外,确实从父类到子类,与Java一样);先子类的静态——>实例,在父类静态——>实例…………父类构造方法——>子类构造方法
执行顺序:
1. 初始化ChildClass的静态字段(按声明顺序)
2. 初始化ChildClass的静态构造函数
3. 初始化ChildClass的实例字段
4. 调用ChildClass的构造函数,并在此中断, 调用ParentClass的构造函数, 导致ParentClass开始初始化
5. 初始化ParentClass的静态字段
6. 初始化ParentClass的静态构造函数
7. 初始化ParentClass的实例字段
8. 调用ParentClass的实例构造函数
9.ParentClass初始化完毕, 调用ChildClass的构造函数,完成创建