Java初始化变量是使用变量前必须完成的操作,不同类型的变量初始化规则、默认值情况、初始化时机都有明显区别,若不了解这些规则很容易写出有问题的代码。下面我们就来详细梳理Java初始化变量的各类注意点。

不同作用域变量的初始化规则差异
局部变量必须显式初始化
局部变量指的是定义在方法、构造方法、代码块内部的变量,这类变量不会获得默认值,必须在使用前显式完成初始化,否则会直接导致编译错误。
比如下面这段代码就会编译失败:
public class InitDemo {
public void test() {
int num;
// 此处直接使用未初始化的num,编译会报错
System.out.println(num);
}
}
正确的写法是在使用前给num赋值:
public class InitDemo {
public void test() {
int num;
num = 10;
System.out.println(num);
}
}
成员变量有默认值无需强制初始化
成员变量是定义在类内部、方法外部的变量,这类变量会在对象实例化时自动获得默认值,不需要强制显式初始化就可以使用。
不同数据类型的成员变量默认值如下:
| 数据类型 | 默认值 |
|---|---|
| byte、short、int、long | 0 |
| float、double | 0.0 |
| char | 'u0000'(空字符) |
| boolean | false |
| 引用类型(如String、自定义对象) | null |
示例代码如下:
public class MemberVarDemo {
// 成员变量,未显式初始化
private int age;
private String name;
public void printInfo() {
// 可以直接使用,不会报错
System.out.println("年龄:" + age);
System.out.println("姓名:" + name);
}
}
static静态变量的初始化规则
static修饰的静态变量属于类本身,不属于某个实例对象,会在类加载阶段完成初始化,同样有默认值,规则和非静态成员变量一致。如果显式赋值的话,赋值操作会在类加载的初始化阶段执行。
public class StaticVarDemo {
// 静态变量,有默认值0
private static int count;
// 显式赋值的静态变量
private static int maxCount = 100;
public static void printCount() {
System.out.println("count默认值:" + count);
System.out.println("maxCount赋值后的值:" + maxCount);
}
}
初始化顺序的注意点
当一个类中同时存在静态变量、成员变量、构造方法时,初始化顺序是有固定规则的:
- 首先执行静态变量和静态代码块的初始化,静态部分的初始化只在类第一次加载时执行一次,优先级高于非静态部分
- 然后是成员变量的初始化和实例代码块的执行,这部分在每次创建对象时都会执行
- 最后是构造方法的执行
示例验证代码:
public class InitOrderDemo {
// 静态变量
private static String staticVar = initStaticVar();
// 静态代码块
static {
System.out.println("静态代码块执行");
}
// 成员变量
private String memberVar = initMemberVar();
// 实例代码块
{
System.out.println("实例代码块执行");
}
// 构造方法
public InitOrderDemo() {
System.out.println("构造方法执行");
}
private static String initStaticVar() {
System.out.println("静态变量初始化");
return "staticVar";
}
private String initMemberVar() {
System.out.println("成员变量初始化");
return "memberVar";
}
public static void main(String[] args) {
System.out.println("第一次创建对象:");
new InitOrderDemo();
System.out.println("第二次创建对象:");
new InitOrderDemo();
}
}
运行后输出结果为:
静态变量初始化 静态代码块执行 第一次创建对象: 成员变量初始化 实例代码块执行 构造方法执行 第二次创建对象: 成员变量初始化 实例代码块执行 构造方法执行
可以看到静态部分只在第一次类加载时执行了一次,后续创建对象不会再执行静态部分的初始化。
其他需要注意的细节
数组初始化的问题
如果是声明数组变量,数组引用本身如果是成员变量会有默认值null,但数组元素如果是基本类型,会在数组实例化后自动赋默认值;如果是引用类型,数组元素默认值为null。如果数组是局部变量,同样需要先初始化数组引用才能使用。
public class ArrayInitDemo {
// 成员变量数组,默认值为null
private int[] memberArr;
public void test() {
// 局部变量数组,未初始化不能使用
int[] localArr;
// localArr = new int[3]; 如果注释掉这行,下面使用localArr会编译报错
localArr = new int[3];
// 数组实例化后,元素有默认值0
System.out.println(localArr[0]);
}
}
避免重复初始化
如果变量已经通过默认值或者显式赋值完成了初始化,不要在没有必要的情况下再次重复赋值,这样会增加不必要的代码开销,也可能引发逻辑错误。比如成员变量已经显式赋值,又在构造方法中赋了相同的值,就属于多余操作。
final变量的初始化要求
被final修饰的变量属于常量,一旦赋值就不能再修改,它的初始化要求更严格:如果是final成员变量,必须在声明时、实例代码块中或者构造方法中完成初始化,三者选其一;如果是final静态变量,必须在声明时或者静态代码块中完成初始化,否则会编译报错。
public class FinalVarDemo {
// final成员变量,声明时初始化
private final int num1 = 10;
// final成员变量,实例代码块中初始化
private final int num2;
{
num2 = 20;
}
// final成员变量,构造方法中初始化
private final int num3;
public FinalVarDemo() {
num3 = 30;
}
// final静态变量,声明时初始化
private static final int STATIC_NUM1 = 100;
// final静态变量,静态代码块中初始化
private static final int STATIC_NUM2;
static {
STATIC_NUM2 = 200;
}
}