您的位置:首页 > 编程语言 > Java开发

java成员变量的初始化顺序

2013-02-22 18:22 211 查看
1:java中静态成员的初始化顺序
public class TestClassInitialize {

public static void main(String[] args) {

System.out.println("第一次调用:");
B b = new B();
System.out.println("第二次调用:");
b = new B();
}

}

class A {

private static int a = setA();
private int a1 = setA1();

static{
System.out.println("--父类静态代码块");
}

private static int setA() {
System.out.println("-父类静态变量……");
return 0;
}

public int setA1() {
System.out.println("---父类成员变量……非静态变量");
return 0;
}

public A() {
System.out.println("----父类构造函数");
}

}

class B extends A {

private static int b = setB();
private int b1 = setB1();

static{
System.out.println("--子类静态代码块");
}

private static int setB() {
System.out.println("-子类静态变量……");
return 0;
}

public int setB1() {
System.out.println("---子类成员变量……非静态变量");
return 0;
}

public B() {
System.out.println("----子类构造函数");
}
}


结果:

第一次调用:

-父类静态变量……

--父类静态代码块

-子类静态变量……

--子类静态代码块

---父类成员变量……非静态变量

----父类构造函数

---子类成员变量……非静态变量

----子类构造函数

第二次调用:

---父类成员变量……非静态变量

----父类构造函数

---子类成员变量……非静态变量

----子类构造函数

由此可见:java中正常的实例化顺序是:父类实例化--》成员变量--》构造函数。加入静态类型之后会初始化所有的静态类型(包括子类和父类),然后才是正常的初始化:父类静态类型--》子类静态类型--》父类实例化--》成员变量--》构造函数。静态类型的初始化顺序都是先变量后程序块。

在C#中类中,静态成员有:静态变量、静态函数和静态构造函数,而在java中是没有静态构造函数的,取而代之的是静态代码块。静态成员一般放在静态区,而且是属于类的,所以我们不用实例化对象,直接调用静态函数,比如工具类的方法一般声明为静态函数。C#和java静态成员的初始化顺序是不一样的。


1.c#中静态成员的初始化顺序

class A

{

    static int a = setA();//静态变量

    int a1 = setA1();//非静态变量

 

    private static int setA1()

    {

        Console.WriteLine("父类非静态变量");

        return 1;

    }

 

    public static int setA()

    {

        Console.WriteLine("父类静态变量");

        return 1;

    }

 

    public A()//构造函数

    {

        Console.WriteLine("父类构造函数");

    }

 

    static A()//静态构造函数

    {

        Console.WriteLine("父类静态构造函数");

    }

}

 

class B : A

{

    static int b = setB();//静态变量

    int b1 = setB1();//非静态变量

 

    private static int setB1()

    {

        Console.WriteLine("子类非静态变量");

        return 1;

    }

 

    public static int setB()

    {

        Console.WriteLine("子类静态变量");

        return 1;

    }

 

    public B()//构造函数

    {

        Console.WriteLine("子类构造函数");

    }

 

    static B()//静态构造函数

    {

        Console.WriteLine("子类静态构造函数");

    }

}

 

class Program

{

    static void Main(string[] args)

    {

        Console.WriteLine("第一次调用。。。");

        B b = new B();

        Console.WriteLine("第二次调用。。。");

        b = new B();

    }

}


结果如下:

第一次调用。。。

-子类静态变量

--子类静态构造函数

---子类非静态变量

----父类静态变量

-----父类静态构造函数

------父类非静态变量

--------父类构造函数

---------子类构造函数

第二次调用。。。

-子类非静态变量

--父类非静态变量

---父类构造函数

----子类构造函数

从这里我们可以看到,静态变量和静态构造函数只会在类的第一次实例化时进行初始化,第二次就是正常的初始化了。在正常实例化中,初始化的顺序是:成员变量 -> 父类实例化 -> 构造函数。如果有静态类型的话,就会先初始化静态类型,于是顺序就变成了:静态变量 -> 静态构造函数 -> 成员变量 -> 父类实例化 -> 构造函数。在父类实例化中,顺序也是这样的。


2.1.一道笔试题

classA

{

    publicstatic int X;

    staticA()

    {

        X = B.Y + 1;

    }

}

classB

{

    publicstatic int Y = A.X + 1;

    staticB() { }

    staticvoid Main()

    {

        Console.WriteLine("X={0},Y={1}", A.X, B.Y);

    }

}

程序会从B类中的Main()开始执行,所以先初始化静态变量Y,而Y要调用A.X,调用A类静态构造函数A(),此时B.Y未初始化默认为0,所以X=1,再回到B的静态变量初始化中Y就是2了。初始化完成后,进入Main(),打印X=1,Y=2。意外吧!


3.总结

c#的初始化顺序看起来比较有规律,父类在子类中初始化,先静态后常规;而java则是先初始化全部静态类型(先父后子),再父类实例化,最后子类。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: