java成员变量的初始化顺序

来源:互联网 发布:plc编程软件通用版 编辑:程序博客网 时间:2024/04/29 22:13
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则是先初始化全部静态类型(先父后子),再父类实例化,最后子类。








原创粉丝点击