class文件结构[2] static final、static、final、普通类型成员变量的赋初值

来源:互联网 发布:淘宝账号和密码共享 编辑:程序博客网 时间:2024/05/20 22:00

不考虑作用域修饰符,成员变量的类型有:

static final 类型、仅static类型、仅final类型、普通类型

并且,我们在定义成员变量的时候,还可以通过=赋初值。(其中包含final时强制要求赋初值)

那么,这些赋值操作都是在哪个阶段完成的呢?

 

按照执行的先后顺序

1.        对于staticfinal类型成员变量,会在class文件的Fields中增加ConstantValue属性,在准备阶段,就由虚拟机设置好常量值

2.        对于仅static类型成员变量,会在准备阶段,设置默认初始值,在初始化阶段,将赋值语句和static{}代码块合并成<clinit>方法,在<clinit>方法中赋值

3.        对于仅final类型成员变量、普通成员变量,会将赋值语句和原构造函数合并,在新构造函数中赋值(虽然仅final类型成员变量也有ConstantValue属性,但是其作为实例成员变量,只有在堆上分配了对象以后才能赋值,所以只能是到了这里才赋值。所以此时的ConstantValue属性其实并没有什么用)

final类型成员变量,编译器会要求要么在定义时赋初值,要么在构造函数中赋初值。

普通成员变量,如果没有设置初始值,也会为其设置默认初始值。(应该也是在上述的第3阶段中,在堆中分配了对象的内存空间以后)

 

默认初始值的规则如下

类型

默认初始值

int/byte/short/char/boolean

0

long

0

float

0

double

0

引用

null

 

以如下代码为例(使用double类型验证,因为int类型会直接将数值生成到字节码指令中去)

 Java Code 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

 

package com.test.a;

public class Test {
    
    
private double m1;
    
private double m2=200d;
    
    
private static double m3;
    
private static double m4=400d;
    
    
private final double m5=500d;
    
    
public static final double m6=600d;
    
    
static{
        m4=700d;
    }
    
    
public Test(){
        m2=800d;
    }
    
    
public void printUnsignedMember(){
        System.out.println(
"m1="+m1);
        System.out.println(
"m3="+m3);
    }
    
}

 

常量池中的内容为

 

m6具有ConstantValue属性,指向常量池中的600d,会在准备阶段就设置初始值。



<clinit>将仅static类型成员变量的赋值语句和static{}静态代码块合并,这里设置了m4


 

<init>将构造函数中的语句和其他类型成员变量的赋值语句合并,这里设置了m2m5


 

执行结果如下,可以看到m1m3默认值

 

 

 

阅读全文
0 0
原创粉丝点击