变量可能尚未初始化错误


72

当我尝试编译时:

public static Rand searchCount (int[] x)
{
    int a ;
    int b ;

    ...

    for (int l= 0; l<x.length; l++)
    {
        if (x[l] == 0)
        a++ ;
        else if (x[l] == 1)
        b++ ;
    }

    ...

}

我得到这些错误:

Rand.java:72: variable a might not have been initialized
                a++ ;
                ^
Rand.java:74: variable b might not have been initialized
                b++ ;
                ^
2 errors

在我看来,我在方法的顶部对其进行了初始化。怎么了

Answers:


110

声明了它们,但没有初始化它们。初始化它们是将它们设置为等于一个值:

int a;        // This is a declaration
a = 0;        // This is an initialization
int b = 1;    // This is a declaration and initialization

因为未初始化变量,但a++for循环中增加了变量(例如),所以会出现错误。

Java原语具有默认值,但如下一位用户所述

当声明为类成员时,它们的默认值为零。局部变量没有默认值


22
也许“ int b = 0;” 是“声明和初始化”。
阿伦(Arun)2010年

对于将来的访问者...当潜在的未初始化变量是类成员时,另请参见Java中的默认值和初始化
jww

3
有人可以解释一下这是怎么可能的,因为原语不能有空值,它们的默认值是0,为什么它不显示未初始化的错误?
Srujan Barai

5
@SrujanBarai当声明为类成员时,其默认值为零。局部变量没有默认值。
user207421 '18

如果“ a”是泛型的怎么办?
Veco

85

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

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

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


8

如果将它们声明为类的字段,则它们将真正用0初始化。

您有点困惑,因为如果您写:

class Clazz {
  int a;
  int b;

  Clazz () {
     super ();
     b = 0;
  }

  public void printA () {
     sout (a + b);
  }

  public static void main (String[] args) {
     new Clazz ().printA ();
  }
}

然后此代码将打印“ 0”。这是因为在创建Clazz的新实例时将调用特殊的构造函数。首先super ()将被调用,然后字段a将被隐式初始化,然后b = 0将执行line 。


静态成员可能以其他方式获得默认值。
sziraqui

4

您声明了它们,但未初始化。

int a; // declaration, unknown value
a = 0; // initialization
int a = 0; // declaration with initialization

3

您声明了它们,但未使用值对其进行初始化。添加如下内容:

int a = 0;

2

您在方法开始时声明了它们,但从未初始化它们。初始化会将它们设置为等于一个值,例如:

int a = 0;
int b = 0;

2

您声明了它们,但没有为它们提供初始值-因此,它们是未初始化的。尝试类似:

public static Rand searchCount (int[] x)  
{ 
  int a = 0 ;  
  int b = 0 ; 

警告应该消失了。


2

想象一下,如果循环中x [l]既不是0也不是1会发生什么。在这种情况下,a和b将永远不会被分配给它们并且具有未定义的值。您必须将它们都初始化为某个值,例如0。


2

在使用之前,最好在方法块中初始化局部变量。这是初学者可能犯的错误。

  public static void main(String[] args){
    int a;
    int[] arr = {1,2,3,4,5};
    for(int i=0; i<arr.length; i++){
        a = arr[i];
    }
    System.out.println(a);
  }

您可能希望控制台将显示“ 5”,但编译器将抛出“变量a可能未初始化”错误。尽管可能会认为变量a在for循环内已“初始化”,但编译器并不这么认为。如果arr.length是0怎么办?for循环根本不会运行。因此,编译器将variable a might not have been initialized指出潜在的危险,并要求您初始化变量。

为避免此类错误,只需在声明变量时对其进行初始化。

int a = 0;

1

您尚未初始化ab,仅对其进行了声明。有细微的差别。

int a = 0;
int b = 0;

至少这是针对C ++的,我认为Java是相同的概念。


您不能从C ++派生它。Java中的局部变量不会自动获取默认值(但如果Java的设计不同,则可以获取默认值),但是实例变量和类变量(“静态”)的确会获取默认值。
Peter Mortensen


0

由于没有其他答案引用了Java语言标准,因此我决定编写自己的答案:

在Java中,默认情况下,局部变量不使用特定值初始化(例如,与类字段不同)。根据语言规范(第4.12.5节),可以阅读以下内容:

在使用局部变量(第14.4节,第14.14节)之前,必须通过初始化(第14.4节)或赋值(第15.26节)为它明确赋一个值,并可以使用确定赋值规则(第§1节)进行验证。 16(确定分配))。

因此,由于变量ab没有初始化:

 for (int l= 0; l<x.length; l++) 
    {
        if (x[l] == 0) 
        a++ ;
        else if (x[l] == 1) 
        b++ ;
    }

操作a++;b++;不能产生任何有意义的结果,无论如何。因此,编译器将其通知您是合乎逻辑的:

Rand.java:72: variable a might not have been initialized
                a++ ;
                ^
Rand.java:74: variable b might not have been initialized
                b++ ;
                ^

然而,需要明白的事实a++;,并b++;不能产生任何有意义的结果已经无关的原因,编译器显示错误。而是因为它是在Java语言规范中明确设置的,

必须为局部变量(第14.4节,第14.14节)明确赋予一个值(...)

为了展示上述观点,让我们将您的代码更改为:

public static Rand searchCount (int[] x) 
{
    if(x == null || x.length  == 0)
      return null;
    int a ; 
    int b ; 

    ...   

    for (int l= 0; l<x.length; l++) 
    {
        if(l == 0)
           a = l;
        if(l == 1)
           b = l;
    }

    ...   
}

因此,即使上面的代码可以正式被证明是有效的(变量ab将与价值始终分配01分别),它是不是编译器的工作,试图分析应用程序的逻辑,而且也没有规则局部变量初始化依赖于此。编译器检查是否变量ab根据被初始化局部变量初始化规则,并进行反应相应地(例如,显示一个编译错误)。

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.