先來看看一段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的構造函數,完成創建