码迷,mamicode.com
首页 > 编程语言 > 详细

Java中初始化的顺序问题小结

时间:2015-06-17 19:52:18      阅读:168      评论:0      收藏:0      [点我收藏+]

标签:

以下内容有一部分是自己的总结,还有一部分是借鉴别人的总结。

 

一.基础概念:

1.构造方法:

构造方法用于执行类的实例初始化工作 ,构造方法又称构造函数。创建对象时,根据传入的参数列表,将自动调用相应的构造方法。  每个类都有构造方法,如果没有显示声明构造方法,编译器会自动生成一个默认的无参数的构造方法。默认构造方法实例化对象,并将未赋值的字段赋予默认值。

注意:如果声明了带有参数的构造方法,编译器则不会自动生成默认的无参数的构造方法,此时如果需要无参数的构造方法,则需要显示声明。

 

2.初始化代码块:

(1)静态初始化代码块:静态初始化代码块用于实现初始化类所需的操作,静态构造初始化代码块用于初始化静态数据,或用于执行仅需一次的特定操作,在创建第一个实例或引用任何静态成员之前,将自动调用静态初始化代码块。类的静态初始化代码块在给定程序中至多执行一次。  当初始化一个类时,在执行静态初始化代码之前,首先将该类中所有静态字段初始化为它们的默认值,然后依次按照静态初始化代码块中的代码执行各个静态字段的初始化。

(2)实例初始化代码块:实例初始化代码块用于初始化实例或对象所需的操作。实例初始化代码块用于初始化实例数据。在创建对象实例之前,将自动执行实例初始化代码块。  当创建一个类时,在执行实例初始化代码之前,首先将该类中的所有实例字段初始化为它们的默认值,然后依次执行各个实例字段的初始化。

 

 

 

二.初始化顺序:

 

静态字段/实例字段可以在声明时同时赋初值,也可以在静态/实例代码块中初始化,或者在构造方法中赋初值。

 

Java类初始化时,首先初始化静态字段,故在给实例字段赋初始值时,可以引用类中定义的静态字段(包括从父类继承的静态字段)。反之不成立。

 

字段的初始化按位置顺序执行,故后续位置的字段的初始化,可以使用之前初始化的字段。但如果在字段初始化中使用后续的字段,则会产生编译错误。

 

常量字段只能被赋值一次,否则会产生编译错误。

 

在创建第一个实例或引用任何静态成员之前,将自动调用静态初始化代码块,执行静态初始化;在创建第一个实例时,将自动调用实例初始化代码块,执行实例初始化。类的静态初始化在给定的程序中至多执行一次,对象的实例初始化则每次创建对象都要执行。

 

 

 

 

 

静态初始化执行顺序:

 

在创建第一个实例或引用任何静态成员之前,如果程序运行中,指定类没有静态初始化,则静态初始化按下列顺序执行:

 

(1)执行初始化类的父类的静态初始化(与类的静态初始化顺序一致)

 

(2)类中所有静态字段的初始化为它们的默认值,或按声明时的赋值初始化。

 

(3)依次按静态初始化代码块中的代码执行各个静态字段的初始化。

 

 

 

 

 

实例初始化属性:

 

在创建类的第一个实例时,如果程序运行中,指定类没有执行静态初始化,则先执行静态初始化,然后执行实例初始化。实例初始化按下列顺序执行:

 

(1)执行初始化类的父类的实例初始化(与类的实例初始化顺序一致)。

 

(2)类中的所有实例字段初始化为它们的默认值,或按声明时的赋值初始化。

 

(3)依次按实例初始化代码块中的代码,执行相应的初始化。

 

(4)依次按相应实例构造方法中的代码块,执行相应的初始化。

 

 

三.一些特例:

1.有静态变量和实例变量的初始化顺序:(静态变量、静态初始化块)>(变量、初始化块)>构造器

例:

public class InitialOrderTest{
     public static String staticField="静态变量";
     public String field="变量";
  static{
  System.out.println(staticField);
  System.out.println("静态初始化块");
  }
  {
  System.out.println(field);
  System.out.println("初始块");
  }
  public InitialOrderTest(){
  System.out.println("构造器");
  }
  public static void main(String[] args){
  new InitialOrderTest();
  }

}


运行以上代码,我们会得到如下的输出结果:
静态变量
静态初始化块
变量
初始化块
构造器

 

2.对于继承关系的初始化顺序:并不是父类完全初始化完毕后才进行子类的初始化,实际上子类的静态变量和静态初始化块的初始化是在父类的变量、初始化块和构造器初始化之前就完成了。 

 

 

class Parent{
  public static String p_StaticField="父类--静态变量";
  public String p_Field="父类--变量";
  static{
  System.out.println(p_StaticField);
  System.out.println("父类--静态初始化块");
  }
  {
  System.out.println(p_Field);
  System.out.println("父类--初始化块");
  }
  public Parent(){
   System.out.println("父类--构造器");
  }
}

 

public class SubClass extends Parent{
  public static String s_StaticField="子类--静态变量";
  public String s_Field="子类--变量";
  static{
  System.out.println(s_StaticField);
  System.out.println("子类--静态初始化块");
  }

      {

       System.out.println("子类--初始化块");

      }

      public SubClass(){

       System.out.println("子类--构造器");

      }
     public static void main(String[] args){

        new SubClass();

  }

}

 

运行结果:

父类--静态变量

父类--静态初始化块

子类--静态变量

子类--静态初始化块

父类--变量

父类--初始化块

父类--构造器

子类--变量

子类--初始化块

子类--构造器

 

3.实例变量,实例初始化块,静态变量,静态变量初始化块的顺序是不一定的,按照它们在类中的顺序来定。
例:

public class TestOrder{
  public static TestA a=new TestA();
  static{
  System.out.println("静态初始化块");
  }
  public static TestB b=new TestB();
  public static void main(String[] args){
  new TestOrder();
  }
}

class TestA{
  public TestA(){
  System.out.println("Test--A");
  }
}

class TestB{
  public TestB(){
  System.out.println("Test--B");
  }
}

运行结果:

Test--A

静态初始化块

Test--B

 

Java中初始化的顺序问题小结

标签:

原文地址:http://www.cnblogs.com/navy-runner/p/4584145.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!