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

Posted 赵庆-BUPT

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了类变量和实例变量及其初始化相关的知识,希望对你有一定的参考价值。

0.基本概念

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

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

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

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

1.类变量初始化

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

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

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

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

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

  初始化顺序确定规则

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

  (2)static变量初始化的方式有两种:定义时初始化和static代码块中初始化。因此,在类变量初始化时机时(上述的3种情形)java虚拟机会按照代码中的顺序依次执行static变量定义语句和static代码块。(两种初始化方式的示例代码如下)

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

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

  根据上述的初始化顺序确定规则,可以确定初始化顺序如下:

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

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

2.实例变量初始化

  实例变量初始化是在创建该类的对象时进行的,确定初始化顺序的规则下:

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

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

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

  根据上述初始化顺序规则,可以确定的初始化顺序如下:

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

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

3.实例

  

 

以上是关于类变量和实例变量及其初始化的主要内容,如果未能解决你的问题,请参考以下文章

Java中的静态变量实例变量和局部变量及其特征

继承链中类实例变量的初始值

java中成员变量代码块构造函数运行顺序

类初始化和实例初始化

类加载器实例化时的顺序

类加载器实例化时的顺序