java成员变量的初始化顺序
2013-02-22 18:22
211 查看
1:java中静态成员的初始化顺序
结果:
第一次调用:
-父类静态变量……
--父类静态代码块
-子类静态变量……
--子类静态代码块
---父类成员变量……非静态变量
----父类构造函数
---子类成员变量……非静态变量
----子类构造函数
第二次调用:
---父类成员变量……非静态变量
----父类构造函数
---子类成员变量……非静态变量
----子类构造函数
由此可见:java中正常的实例化顺序是:父类实例化--》成员变量--》构造函数。加入静态类型之后会初始化所有的静态类型(包括子类和父类),然后才是正常的初始化:父类静态类型--》子类静态类型--》父类实例化--》成员变量--》构造函数。静态类型的初始化顺序都是先变量后程序块。
在C#中类中,静态成员有:静态变量、静态函数和静态构造函数,而在java中是没有静态构造函数的,取而代之的是静态代码块。静态成员一般放在静态区,而且是属于类的,所以我们不用实例化对象,直接调用静态函数,比如工具类的方法一般声明为静态函数。C#和java静态成员的初始化顺序是不一样的。
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();
}
}
从这里我们可以看到,静态变量和静态构造函数只会在类的第一次实例化时进行初始化,第二次就是正常的初始化了。在正常实例化中,初始化的顺序是:成员变量 -> 父类实例化 -> 构造函数。如果有静态类型的话,就会先初始化静态类型,于是顺序就变成了:静态变量 -> 静态构造函数 -> 成员变量 -> 父类实例化 -> 构造函数。在父类实例化中,顺序也是这样的。
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。意外吧!
c#的初始化顺序看起来比较有规律,父类在子类中初始化,先静态后常规;而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则是先初始化全部静态类型(先父后子),再父类实例化,最后子类。
相关文章推荐
- Java 类加载顺序与成员变量初始化
- [转]Java初始化顺序总结 - 静态变量、静态代码块、成员变量、构造函数
- Java类成员变量、普通成员变量、初始化块、构造方法的初始化和执行顺序
- java基础---静态变量,成员变量,局部变量及类的初始化顺序
- Java初始化顺序总结及其程序执行过程图- 静态变量、静态代码块、成员变量、构造函数
- Java中成员变量的初始化顺序浅析
- java堆空间子父类顺序(1)开辟空间都为0(2)父类初始化不管值(3)把成员变量赋值的显示初始化(4)构造代码块(5)子函数初始化
- java成员变量的初始化顺序
- Java中创建对象时,初始化成员变量的代码的执行顺序
- Java初始化顺序总结 - 静态变量、静态代码块、成员变量、构造函数
- java学习个人笔记---类成员变量初始化顺序
- Java 代码块、成员变量初始化、构造函数初始化顺序
- Java中构造代码块和成员变量初始化的顺序关系
- 从类变量成员初始化顺序,理解java语法[1]
- Java成员变量初始化和执行顺序
- Java 构造方法和成员变量初始化顺序
- Java成员变量初始化顺序
- java基础,静态变量,静态初始化块,初始化快,成员变量的初始化顺序
- java中成员 变量的初始化顺序
- Java初始化顺序总结 - 静态变量、静态代码块、成员变量、构造函数