Java类的初始化、变量的初始化 Java类的初始化、变量的初始化 Java变量的初始化问题探究

Java类的初始化、变量的初始化


知识点

  • Java常量,   final 修饰,值被设定后不能再被修改
  • 静态变量里,  static 修饰,顾名思义,无须创建对象,便可在内存中申请一个存储空间进行存储
  • 成员变量,  也称实例变量,它随着当前对象的建立而建立,随着对象的销毁而销毁,存在于对象所在的堆内存
  • 构造器,创建class对象时执行
  • 静态初始化块  ,执行优先级高于非静态的初始化块,它会在对象装载到 jvm的时候执行一次,执行完成便销毁,只能初始化 static 修饰的变量
  • 非静态初始化块,执行的时候如果有静态初始化块,先执行静态初始化块再执行非静态初始化块,在每个对象生成时都会被执行一次,它可以初始化类的实例变量。但它会在构造函数执行之前被执行

类的初始化顺序

Java中类初始化顺序,依次是(静态变量、静态初始化块)>(变量、初始化块)>构造器。。


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成员变量是如何初始化的呢在何时?在程序中的什么位置?

下面看个小程序。

[java]  view plain  copy
  1. public class TestC {  
  2.     /* 
  3.      * 定义成员变量 
  4.      * 尾数为1表示定义时进行初始化赋值 
  5.      * 尾数为2表示在代码块中进行初始化赋值 
  6.      * 尾数为3表示在构造函数中进行初始化赋值 
  7.      * 尾数为4表示在静态代码块中进行初始化赋值 
  8.      * 尾数为5表示不初始化赋值 
  9.      */  
  10.     /* 
  11.      * 普通成员变量  
  12.      */  
  13.     int field_a1 = 5;  
  14.     int field_a2;  
  15.     int field_a3;  
  16.     //报错:不能再静态代码块中使用非静态变量。 Cannot make a static reference to the non-static field field_a4  
  17.     //int field_a4;  
  18.     int field_a5;  
  19.     /* 
  20.      * final 成员变量 
  21.      */  
  22.     final int  field_b1 = 5;  
  23.     final int  field_b2;  
  24.     final int  field_b3;  
  25.     //报错:不能再静态代码块中使用非静态变量。Cannot make a static reference to the non-static field field_b4  
  26.     //final int  field_b4;  
  27.     //报错:未初始化 。The blank final field field_b5 may not have been initialized  
  28.     //final int  field_b5;  
  29.     /* 
  30.      * static成员变量 
  31.      */  
  32.     static int field_c1 = 5;  
  33.     static int field_c2;  
  34.     static int field_c3;  
  35.     static int field_c4;  
  36.     static int field_c5;  
  37.     /* 
  38.      * static final 成员变量 
  39.      */  
  40.     static final int field_d1 = 5;  
  41.     //报错:未初始化 。The blank final field field_d2 may not have been initialized  
  42.     //static final int field_d2;  
  43.     //报错:未初始化 。The blank final field field_d3 may not have been initialized  
  44.     //static final int field_d3;  
  45.     static final int field_d4;  
  46.     //报错:未初始化 。The blank final field field_d5 may not have been initialized  
  47.     //static final int field_d5;  
  48.       
  49.     //代码块  
  50.     {  
  51.           
  52.         field_a2 = 5;  
  53.         field_b2 = 5;  
  54.         field_c2 = 5;  
  55.         //field_d2 = 5;  
  56.     }  
  57.       
  58.     //静态代码块  
  59.     static{  
  60.         //field_a4 = 5;  
  61.         //field_b4 = 5;  
  62.         field_c4 = 5;  
  63.         field_d4 = 5;  
  64.     }  
  65.       
  66.     //构造函数  
  67.     public TestC(){  
  68.         field_a3 = 5;  
  69.         field_b3 = 5;  
  70.         field_c3 = 5;  
  71.         //field_d3 = 5;  
  72.           
  73.     }  
  74. }  

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

下面是TestC.jad文件。反编译文件

[java]  view plain  copy
  1. 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. }  

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

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

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

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


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

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

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

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


参考博文:https://blog.csdn.net/wlcw16/article/details/8506846


猜你喜欢

转载自blog.csdn.net/weixin_37766296/article/details/80548111