`

(静态)初始化块、(类)成员变量、构造函数的初始化顺序

 
阅读更多

本文转自此处

源代码:

public class Teststaticblock 
{ 
	public Teststaticblock() 
	{ 
  		this("second"); 
  		System.out.println("begin constructor"); 
  		System.out.println(s_a); //111
  		System.out.println(s_b); //222
  		System.out.println(c); //333
  		System.out.println(d); //d的值为什么是4,却不是444??
				       //因为程序会按照初始化块和实例Field生命语句的先后顺序来执行,
				       //先赋给d的值444会被后赋给d的值4覆盖掉,所以d的最终值为4.
		//  this("second");//call to this must be first statement in constructor 
  		s_a=1111; 
  		s_b=2222; 
  		c=3333; 
  		d=4444; 
  		System.out.println(s_a); //1111
  		System.out.println(s_b); //2222
  		System.out.println(c); //3333
  		System.out.println(d); //4444
  		System.out.println("end constructor"); 
	} 
	public Teststaticblock(String s) 
	{ 
  		System.out.println("begin second constructor"); 
  		System.out.println("end second constructor"); 
	} 
	public static void main(String args[]) 
	{ 
  		System.out.println("begin main"); 
  		System.out.println(s_a); 
 		System.out.println(s_b); //s_b的值为什么是2,却不是22??
					 //因为程序会按照静态初始化块和静态Field声明语句的先后顺序来执行,先赋给s_b的值22
					 //会被后赋给s_b的值2覆盖掉,所以s_b最终的值为2.
		//  System.out.println(c);
                //non-static variable c cannot be referenced from a static context 
		//  System.out.println(d);
                //non-static variable c cannot be referenced from a static context 
  		s_a=11111; 
  		s_b=22222; 
		//  c=33333;//non-static variable c cannot be referenced from a static context 
		//  d=44444;//non-static variable c cannot be referenced from a static context 
 		System.out.println(s_a); //11111
  		System.out.println(s_b); //22222
		//  System.out.println(c);
                //non-static variable c cannot be referenced from a static context 
		//  System.out.println(d);
                //non-static variable c cannot be referenced from a static context 
  		System.out.println("before new class object"); 
  		Teststaticblock t = new Teststaticblock(); 
  		System.out.println("end new class object"); 
  		System.out.println(s_a);//1111 
  		System.out.println(s_b); //2222
		//  System.out.println(c);
                //non-static variable c cannot be referenced from a static context 
		//  System.out.println(d);
                //non-static variable c cannot be referenced from a static context 
  		s_a=111111; 
  		s_b=222222; 
		//  c=333333;//non-static variable c cannot be referenced from a static context 
		//  d=444444;//non-static variable c cannot be referenced from a static context 
  		System.out.println(s_a); //111111
  		System.out.println(s_b); //222222
		//  System.out.println(c);
                //non-static variable c cannot be referenced from a static context 
		//  System.out.println(d);
                //non-static variable c cannot be referenced from a static context 
  		System.out.println("end main"); 
	} 

	static int s_a=1; 
	int c=3; 
	{ 
  		System.out.println("begin block"); 
  		System.out.println(s_a); //11111
  		System.out.println(s_b); //22222
  		System.out.println(c); //3
		//  System.out.println(d);//illegal forward reference 
  		s_a=111; 
  		s_b=222; 
  		c=333; 
  		d=444; 
  		System.out.println(s_a); //111
  		System.out.println(s_b); //222
  		System.out.println(c); //333
		//  System.out.println(d);//illegal forward reference 
  		System.out.println("end block"); 
	} 
	static 
	{ 
  		System.out.println("begin static block"); //begin static block
  		System.out.println(s_a);//1
		//为什么不能输出s_b的值,却可以给s_b赋值??
		//  System.out.println(s_b);//illegal forward reference 
		//  System.out.println(c);
                //non-static variable c cannot be referenced from a static context 
		//  System.out.println(d);
                //non-static variable c cannot be referenced from a static context 
  		s_a=11; 
  		s_b=22; 
  		System.out.println(s_a); //11
		//  System.out.println(s_b);//illegal forward reference 
		//  System.out.println(c);
                //non-static variable c cannot be referenced from a static context 
		//  System.out.println(d);
                //non-static variable c cannot be referenced from a static context 
  		System.out.println("end static block"); 
	} 
	int d=4; 
	static int s_b=2; 

} 

 运行结果:

/*
begin static block 
1 
11 
end static block 
begin main 
11 
2 
11111 
22222 
before new class object 
begin block 
11111 
22222 
3 
111 
222 
333 
end block 
begin second constructor 
end second constructor 
begin constructor 
111 
222 
333 
4 
1111 
2222 
3333 
4444 
end constructor 
end new class object 
1111 
2222 
111111 
222222 
end main 
*/

 结果分析:

1、在类第一次加载时候,会执行静态成员变量(静态Field)初始化语句和静态初始化块(用static{}包含的部分)。

注意:

a、不管静态成员变量声明语句的实际位置在哪儿,当第一次加载类的时候都会首先对它初始化为缺省值(0,false,null等)。

b、即使静态成员变量声明中使用了显式初始化语句(比如:int x=3),第一次加载类的时候也会先把它初始化为缺省值(此时x为0),然后再按照下面说的要点c来执行赋值语句(x=3)。

c、对于静态成员变量的显式初始化语句和静态初始化块,按照在类中代码出现的先后顺序执行。 

     因此,在上面的例子程序中,我们看到 

      static int s_a=1; 

      static 

      { 

         s_a=11; 

         s_b=22; 

       } 

     static int s_b=2; 

对s_a,s_b会有不同的效果。

类加载时候,s_a,s_b都被初始化为0,然后由于依照代码顺序执行了s_a=1;s_a=11;s_b=22;s_b=2;

结果s_a、s_b分别变成了11和2。 

 

2、当构造类实例时候,会先对实例成员变量初始化为缺省值,然后执行初始化块(用{}括起来的部分),然后执行构造方法。其中:

a、如同1中一样,如果有实例成员变量的显式初始化语句,程序仍然是先将该成员变量初始化为缺省值,然后按照代码在类中出现的先后顺序执行初始化语句或者初始化块。

     如果初始化块位置在初始化语句前面,即使它改变了该成员变量的值,也会被随后执行的初始化语句改回去。 

b、在进入构造方法后,如果构造方法第一句是使用this(...)调用另一构造方法的话,则先执行另一构造方法,然后再执行本构造方法的方法体。这种用法必须让this(...)位于第一句。

 

分享到:
评论

相关推荐

    java 静态非静态 字段方法 子类父类构造_初始化顺序!

    System.out.println("父类--静态初始化块"); } // 初始化块 { System.out.println(p_Field); System.out.println("父类--初始化块"); } // 构造器 public Parent() { System.out.println(...

    关于C++中构造函数初始化成员列表的总结

    1.只能在构造函数初始化列表初始化的成员变量的类型?  a.const成员变量  b.引用类型的成员变量  c.static不能在初始化列表中进行初始化  d.类成员变量中有自定义类型的变量最好在初始化列表中进行初始化 2.初始...

    Java中static静态变量的初始化完全解析

    static所声明的变量在Java中有一个初始化的先后顺序,带着这个问题接下来我们就来进行Java中static静态变量的初始化完全解析:

    C++中类成员变量初始化总结

    考虑一下效率的可以再构造函数的初始化列表中进行。  class CA  {  public:  int data;  ……  public:  CA();  ……  };  CA::CA():data(0)//……#1……初始化列表方式  {  //data = 0;//...

    static成员变量不属于对象的一部分,而是类的一部分,所以程序可以在还没有诞生任何对象的时候就处理此种成员变量

    不要把static成员变量的初始化操作安排在类的构造函数中,因为构造函数可能一再被调用,而static成员变量只实例化一次。也不要把初始化操作安排在头文件中,因为它可能会被载入许多地方,因此也就可能被执行多次。...

    C++ 成员变量的初始化顺序问题详解

    C++ 成员变量的初始化顺序问题详解 问题来源: 由于面试题中,考官出了一道简单的程序输出结果值的题:如下, class A { private: int n1; int n2; public: A():n2(0),n1(n2+2){} void Print(){ cout <&...

    C#静态构造函数用法实例分析

    当我们想初始化一些静态变量的时候,就需要用到静态构造函数了。这个静态构造函数属于类,而不属于实例,就是说这个构造函数只会被执行一次,即:在创建第一个实例或引用任何静态成员之前,由.NET自动调用。 现在...

    C# 静态构造函数使用

    当我们想初始化一些静态变量的时候,需要用到静态构造函数了。这个静态构造函数属于类,而不属于实例,是说这个构造函数只会被执行一次,即:在创建第一个实例或引用任何静态成员之前,由.NET自动调用。  现在碰到...

    Effective C# 使用成员初始化器而不是赋值语句

    无论是类成员(静态变量)合适实例变量,我们都应该充分利用初始化器的语法。 C#编程在,一般在声明一个变量的同时我们会对其进行初始化: 代码如下:1 class Employee 2 { 3 private List<Employee> empList = new ...

    C#中static静态变量的用法实例

    使用 static 修饰符声明属于类型本身而不是属于特定对象的静态成员static修饰符可用于类、字段、方法、属性、运算符、事件和构造函数,但不能用于索引器、析构函数或类以外的类型   静态全局变量 定义:在全局变量...

    java对象初始化顺序验证示例

    以下这段小程序对调用对象构造函数时,父类构造函数、成员变量初始化函数,以及非静态初始化块调用顺序进行验证,不考虑静态成员及静态初始化块

    学习C#静态函数及变量的一个精典例子与代码

     (3)类的静态构造函数在给定应用程序域中至多执行一次:只有创建类的实例或者引用类的任何静态成员才激发静态构造函数 (4)静态构造函数是不可继承的,而且不能被直接调用。 (5)如果类中包含用来开始执行的...

    C#中静态构造函数的几点说明介绍

    不过当我们想初始化一些静态变量的时候就需要用到它了。这个构造函数是属于类的,而不是属于哪里实例的,就是说这个构造函数只会被执行一次。也就是在创建第一个实例或引用任何静态成员之前,由.NET自动调用。 代码...

    详解c# 类的构造方法

    类的静态构造方法是类的成员方法的一种,它的作用是对类中的静态成员进行初始化操作。下面请看代码实例: using System; namespace LycheeTest { class Test { //定义一个静态成员变量 private static int a; /...

    JAVA资格认证:SCJP310-055中文

    声明、初始化并使用基本类型、数组、枚举、静态对象、成员变量和局部变量,使用合法的变量标识符。  定义方法和静态方法,使用符合JavaBean命名规范的方法名。  定义并使用可变参数。正确重写和重载方法并识别...

    C++中静态初始化数组与动态初始化数组详解

    静态初始化的数组的长度必须是在程序中确定的常数,不能是由用户输入的变量 例子: int a[10];//正确 Student stud[10];//正确:Student是一个学生类 int n;cin>>n;int a[n];//错误 int n;cin>>n;Student stud[n];/...

    VC++深入详解源码

    构造函数的作用是对对象本身做初始化工作,也就是给用户提供初始化类中成员变量的一种方式,在类对象有虚表的情况下,构造函数还对虚表进行初始化。 另外,我说:“C++又规定,如果一个类没有提供任何的构造函数,则...

    C++高级参考手册 完全自学 内容详细 讲解通俗易懂

    9.4 静态初始化的依赖因素 9.5 转换连接指定 9.6 小结 9.7 练习 第10章 引用和拷贝构造函数 10.1 C++中的指针 10.2 C++中的引用 10.2.1 函数中的引用 10.2.2 参数传递准则 10.3 拷贝构造函数 10.3.1 传值...

    MFC常用的类及其成员函数简介

    在InitInstance()函数中,创建了一个单文档模板类或多文档模板类(CDocTemplate)的对象,并且在文档模板的构造函数中,系统定义的宏RUNTIME_CLASS创建了文档类对象,框架窗口类对象和视图类对象. 在MFC应用程序中有且仅有...

    提高C#编程水平的50个要点

    使用静态构造函数来初始化静态成员变量  14.用多个构造函数时,利用构造函数链  15.使用using和try/finally来处理资源的释放  16.尽量避免产生资源垃圾  17.尽量避免使用装箱(boxing)和拆箱(unboxing)  18.实现...

Global site tag (gtag.js) - Google Analytics