Java变量的初始化问题探究

对于java的变量,我们知道有成员变量和局部变量。

关于他们的初始化,基本上所有书上都会写。成员变量,java会帮助你初始化,局部变量,则需要程序员自己初始化。

 

对于类的成员变量。不管程序有没有显示的初始化,Java  虚拟机都会先自动给它初始化为默认值。

规则为:

1、整数类型(byte、short、int、long)的基本类型变量的默认值为0。

2、单精度浮点型(float)的基本类型变量的默认值为0.0f。

3、双精度浮点型(double)的基本类型变量的默认值为0.0d。

4、字符型(char)的基本类型变量的默认为 “/u0000”。

5、布尔性的基本类型变量的默认值为 false。

6、引用类型的变量是默认值为 null。

7、数组引用类型的变量的默认值为 null。春关键数组变量的实例后,如果没有没有显示的为每个元素赋值,Java 就会把该数组的所有元素初始化为其相应类型的默认值。

局部变量初始化

 

局部变量声明以后,Java 虚拟机不会自动的为它初始化为默认值。因此对于局部变量,必须先经过显示的初始化,才能使用它。

如果编译器确认一个局部变量在使用之前可能没有被初始化,编译器将报错。


那么,加了修饰的java成员变量是如何初始化的呢?在何时?在程序中的什么位置?

下面看个小程序。

 

public class TestC {  
    /*  
     * 定义成员变量  
     * 尾数为1表示定义时进行初始化赋值  
     * 尾数为2表示在代码块中进行初始化赋值  
     * 尾数为3表示在构造函数中进行初始化赋值  
     * 尾数为4表示在静态代码块中进行初始化赋值  
     * 尾数为5表示不初始化赋值  
     */  
    /*  
     * 普通成员变量   
     */  
    int field_a1 = 5;  
    int field_a2;  
    int field_a3;  
    //报错:不能再静态代码块中使用非静态变量。 Cannot make a static reference to the non-static field field_a4  
    //int field_a4;  
    int field_a5;  
    /*  
     * final 成员变量  
     */  
    final int  field_b1 = 5;  
    final int  field_b2;  
    final int  field_b3;  
    //报错:不能再静态代码块中使用非静态变量。Cannot make a static reference to the non-static field field_b4  
    //final int  field_b4;  
    //报错:未初始化 。The blank final field field_b5 may not have been initialized  
    //final int  field_b5;  
    /*  
     * static成员变量  
     */  
    static int field_c1 = 5;  
    static int field_c2;  
    static int field_c3;  
    static int field_c4;  
    static int field_c5;  
    /*  
     * static final 成员变量  
     */  
    static final int field_d1 = 5;  
    //报错:未初始化 。The blank final field field_d2 may not have been initialized  
    //static final int field_d2;  
    //报错:未初始化 。The blank final field field_d3 may not have been initialized  
    //static final int field_d3;  
    static final int field_d4;  
    //报错:未初始化 。The blank final field field_d5 may not have been initialized  
    //static final int field_d5;  
      
    //代码块  
    {  
        field_a2 = 5;  
        field_b2 = 5;  
        field_c2 = 5;  
        //field_d2 = 5;  
    }  
      
    //静态代码块  
    static{  
        //field_a4 = 5;  
        //field_b4 = 5;  
        field_c4 = 5;  
        field_d4 = 5;  
    }  
      
    //构造函数  
    public TestC(){  
        field_a3 = 5;  
        field_b3 = 5;  
        field_c3 = 5;  
        //field_d3 = 5;  
    }  

然后我们对这个程序生成的.class文件进行反编译,看看他是如何运行的。
下面是TestC.jad文件。反编译文件


 

  1. <span style="font-family:Microsoft YaHei;font-size:18px;">public class TestC  
  2. {  
  3.   
  4.     public TestC()  
  5.     {  
  6.         field_a1 = 5;  
  7.         field_a2 = 5;  
  8.         field_c2 = 5;  
  9.         field_a3 = 5;  
  10.         field_c3 = 5;  
  11.     }  
  12.   
  13.     int field_a1;  
  14.     int field_a2;  
  15.     int field_a3;  
  16.     int field_a5;  
  17.     final int field_b1 = 5;  
  18.     final int field_b2 = 5;  
  19.     final int field_b3 = 5;  
  20.     static int field_c1 = 5;  
  21.     static int field_c2;  
  22.     static int field_c3;  
  23.     static int field_c4 = 5;  
  24.     static int field_c5;  
  25.     static final int field_d1 = 5;  
  26.     static final int field_d4 = 5;  
  27.   
  28. }</span>  



看到这里我们就很有清晰的思路了。

 

对于不加修饰的普通成员变量,无论我们在什么地方对其进行初始化赋值,系统都会默认在构造函数中进行赋值。

对于final变量,无论我们在什么地方进行赋值,系统会默认final变量是在类中进行初始化。

对于static,系统会根据我们的需求,而在不同位置进行初始化。


通过报错,我们可以发现。

final变量必须进行初始化。否则就会报编译错误。The blank final field field_d5 may not have been initialized

static成员变量的初始化发生在类被类加载器(classLoader)加载的时候系统会对没有初始化的静态成员变量在静态区进行默认赋值。

普通成员变量的初始化发生在JVM为类生成实例开辟空间的时候进行默认初始化赋值

原文地址:https://www.cnblogs.com/ihanliu/p/4792179.html