类变量和实例变量及其初始化

0.基本概念

  类变量是指java类中的static数据成员,实例变量则是指java类中的非static数据成员。由于类变量不需要创建一个对象即可访问,而实例变量则必须与一个具体的对象对应,因此类变量和实例变量的初始化时机是不同的。本文主要关注以下3个问题:

  (1)什么时候初始化类变量?什么时候初始化实例变量?

  (2)什么时候会同时初始化类变量和实例变量?

  (3)在(1)、(2)情形下各个类变量和实例变量的初始化顺序?

1.类变量初始化

  1.1 类变量初始化方式

  static变量初始化的方式有两种:定义时初始化和static代码块中初始化。如下代码所示:

1 class A(){  
2    public static int i = 1;//static变量初始化方式一:在定义时初始化
3    static{//static变量初始化方式二:在static代码块初始化static变量
4      System.out.println("statci 代码块");
5      }    
6  }

  1.2 类变量初始化时机

  根据有无被final关键字修饰,类变量的初始化时机不同。被final关键字修饰的类变量在编译时就已经被初始化被放置在常量池中了,而没有被final修饰的类变量则在该类首次使用时被初始化。特别需要注意的是,类变量只在该类首次使用时被初始化,这意味着类变量只会被初始化一次。

  在下列情形下,如果一个java类中没有被final修饰的类变量尚未初始化,那么这些没有被final修饰的类变量将会被初始化:

  (1)访问该类中没有被final修饰的类变量时;

  (2)设置该类中没有被final修饰的类变量时;

  (3)调用该类的static方法。

  1.2 类变量初始化顺序

  类变量初始化会遵循以下三个原则:

  (1)在上述3个情形下,首先会初始化该类中所有没有被final修饰的类变量,然后再执行对应的操作;

  (2)按照代码中的顺序依次执行static变量定义语句和static代码块;

  (3)如果该类有父类且父类的类变量没有初始化,则先初始化父类的类变量;

  (4)如果父类还有父类的话,根据(3)的规则,以此类推。

  根据上述原则,可以确定类变量初始化顺序如下:

//没有继承的情形
static变量初始化和static代码块

//有继承的情形
1.父类的static变量初始化和static代码块
2.子类的static变量初始化和static代码块

/*备注:
类变量初始化只有一次,如果某个java类的类变量已经被初始化过了,则上述过程中的类变量初始化将不再执行
*/

 

2.实例变量初始化

  2.1 实例变量初始化方式

  与类变量初始化方式类似,实例变量初始化方式也有两种:定义时初始化和代码块初始化。示例如下:

1  class A(){  
2    public static int i = 1;//实例变量初始化方式一:在定义时初始化
3 
4    {//实例变量初始化方式二:在代码块初始化实例变量
5      System.out.println("代码块");
6      }    
7  }

  2.2 实例变量初始化时机和顺序

  实例变量初始化是在创建该类的对象时进行的,初始化时遵循的原则是:

  (1)按照代码中的顺序依次执行实例变量定义语句和实例变量代码块;

  (2)如果创建该类的对象时该类的类变量尚未初始化,则先初始化类变量,再初始化实例变量;

  (3)如果该类有父类的话,则先创建一个父类对象;并且,如果父类类变量没被初始化时,先初始化父类的类变量,再初始化父类的实例变量,再调用父类的默认构造器;

  (4)如果父类还有父类的话,根据(3)的规则以此类推,一直到根基类。

  根据上述原则易知,实例变量初始化之前可能会先初始化类变量(这是特别需要留意的一点)。初始化顺序如下:

//没有继承的情形(且该类的类变量未被初始化)
1.static变量初始化和static代码块
2.实例变量初始化和实例变量初始化代码块
3.构造函数

//有继承的情形(且该类和父类的类变量未被初始化)
1.父类的static变量初始化和static代码块
2.子类的static变量初始化和static代码块
3.父类的实例变量初始化和实例变量初始化代码块
4.父类的构造函数
5.子类的实例变量初始化和实例变量初始化代码块
6.子类构造函数

/*备注:
类变量初始化只有一次,如果某个java类的类变量已经被初始化过了,则上述过程中的类变量初始化将不再执行
*/

3.小结

  大家看完如果还不太明白类变量和实例变量的初始化时机和顺序,可以亲自去写一个demo试试,实践才能出真知嘛!

  在这里,只强调两点:

  (1)类变量只会初始化一次;

  (2)类变量和实例变量的初始化时机是不同的,类变量初始化在首次使用该类的时候进行,实例变量的初始化在创建该类的每个对象时都会进行。

  

 

posted @ 2018-03-02 12:38  赵庆-BUPT  阅读(3848)  评论(0编辑  收藏  举报