Java中的默认值和初始化


76

根据我的参考,原始类型具有默认值,而Objects为null。我测试了一段代码。

public class Main {
    public static void main(String[] args) {
        int a;
        System.out.println(a);
    }
}

该行将System.out.println(a);指向一个变量a,指出该错误,variable a might not have been initialized而在给定的引用中,integer将具有0默认值。但是,使用下面的给定代码,它将实际打印出来0

public class Main {
    static int a;
    public static void main(String[] args) {
        System.out.println(a);
    }
}

第一个代码可能会出什么问题?类实例变量的行为与局部变量不同吗?


在第二个中正在打印什么?0?
porfiriopartida

@porfiriopartida是的,第二个代码上印有0。
Michael'Maik'Ardan

应用启动时,静态上下文是init,它正在启动默认值。对于int为0,对于String为空字符串,对于布尔值等,我相信是false。但是出于局部或实例目的,您可以控制它们;您不能保证何时或谁将访问静态属性。
porfiriopartida

这可能与Variable可能尚未初始化error重复。
jww

1
好收获@ Md.AbuNafeeIbnaZahid。完成问题的编辑
Michael'Maik'Ardan

Answers:


77

在第一个代码示例中,amain方法局部变量。在使用方法局部变量之前,需要对其进行初始化。

在第二个代码示例中,aclass成员变量是class,因此它将被初始化为default value。


我注意到方法局部数组变量在使用时没有给出“变量a可能尚未初始化”。是否将声明为数组的方法变量初始化为默认值,而独立变量不是?
Androidcoder

67

请仔细阅读您的参考资料

默认值

声明字段时,不一定总是需要分配值。 编译器会将已声明但未初始化的字段设置为合理的默认值。一般来说,此默认值将为零或null,具体取决于数据类型。但是,通常认为依赖于此类默认值是不好的编程风格。

下表总结了上述数据类型的默认值。

。。。

局部变量略有不同。编译器永远不会为未初始化的局部变量分配默认值。如果无法在声明它的地方初始化本地变量,请确保在尝试使用它之前为其分配一个值。访问未初始化的局部变量将导致编译时错误。


2
我也读过这个,但是数组呢。给本地上下文中使用的数组指定了默认值,但是文档中没有提及它。
Yahya Uddin

对于本地上下文中的数组,有一个很好的解释,可以作为此处的公认答案:stackoverflow.com/questions/13511702/int-array-initialization
gcbound

18

这些是主要因素:

  1. 成员变量(默认为确定)
  2. 静态变量(默认为OK)
  3. 最终成员变量(未初始化,必须在构造函数上设置)
  4. 最终静态变量(未初始化,必须在静态块{}上设置)
  5. 局部变量(未初始化)

注意1:必须在每个实现的构造函数上初始化最终成员变量!

注意2:您必须在构造函数本身的块内初始化最终成员变量,而不是调用用于对其进行初始化的其他方法。例如,这是无效的:

private final int memberVar;

public Foo() {
    //invalid initialization of a final member
    init();
}

private void init() {
    memberVar = 10;
}

注3:数组是Java中的对象,即使它们存储原语也是如此。

注意4:初始化数组时,其所有项均设置为默认值,而与成为成员或本地数组无关。

我将附上一个代码示例,介绍上述情况:

public class Foo {
    //static and member variables are initialized to default values

    //primitives
    private int a; //default 0
    private static int b; //default 0

    //objects
    private Object c; //default NULL
    private static Object d; //default NULL

    //arrays (Note: they are objects too, even if they store primitives)
    private int[] e; //default NULL
    private static int[] f; //default NULL

    //what if declared as final?

    //primitives
    private final int g; //not initialized, MUST set in constructor
    private final static int h; //not initialized, MUST set in a static {}

    //objects
    private final Object i; //not initialized, MUST set in constructor
    private final static Object j; //not initialized, MUST set in a static {}

    //arrays
    private final int[] k; //not initialized, MUST set in constructor
    private final static int[] l; //not initialized, MUST set in a static {}

    //initialize final statics
    static {
        h = 5;
        j = new Object();
        l = new int[5]; //elements of l are initialized to 0
    }

    //initialize final member variables
    public Foo() {
        g = 10;
        i = new Object();
        k = new int[10]; //elements of k are initialized to 0
    }

    //A second example constructor
    //you have to initialize final member variables to every constructor!
    public Foo(boolean aBoolean) {
        g = 15;
        i = new Object();
        k = new int[15]; //elements of k are initialized to 0
    }

    public static void main(String[] args) {
        //local variables are not initialized
        int m; //not initialized
        Object n; //not initialized
        int[] o; //not initialized

        //we must initialize them before usage
        m = 20;
        n = new Object();
        o = new int[20]; //elements of o are initialized to 0
    }
}

8

在声明原始类型值时,需要牢记一些注意事项。

他们是:

  1. 在方法内部声明的值将不会分配默认值。
  2. 声明为实例变量或静态变量的值将分配为0的默认值。

因此,在您的代码中:

public class Main {
    int instanceVariable;
    static int staticVariable;
    public static void main(String[] args) {
        Main mainInstance = new Main() 
        int localVariable;
        int localVariableTwo = 2;
        System.out.println(mainInstance.instanceVariable);
        System.out.println(staticVariable);
       // System.out.println(localVariable); //will throw compilation error
        System.out.println(localVariableTwo);

    }
}

2

是的,实例变量将被初始化为默认值,对于局部变量,您需要在使用前进行初始化

public class Main {
      int instaceVariable; // Instance variable will be initalized to default value
    public static void main(String[] args) {
        int localVariable = 0; // Local Variable Need to initalize before use
    }
}

1

局部变量不获取默认值。它们的初始值是不确定的,没有通过某种方式分配值。在使用局部变量之前,必须先对其进行初始化。

当您在类级别(作为成员即字段)和方法级别声明变量时,会有很大的不同。

如果在类级别声明字段,则它们将根据其类型获得默认值。如果您在方法级别或作为块声明变量(表示{}中的anycode),则不会获得任何值并且保持未定义状态,直到它们以某种方式获得一些初始值(即分配给它们的某些值)为止。


0

所有成员变量都必须加载到堆中,因此在创建类的实例时必须使用默认值进行初始化。在使用局部变量的情况下,它们不会被加载到堆中,它们会存储在堆栈中,直到在Java 7之前使用它们为止,因此我们需要显式初始化它们。


0

在Java中,默认初始化仅适用于类成员的实例变量,而不适用于局部变量。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.