变量可能未被初始化错误

87

我尝试编译这个代码:

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

在我看来,我是在该方法的顶部初始化它们的。出了什么问题?

12个回答

136

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

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

您会收到该错误,因为您尚未初始化变量,但是你在 for 循环中对它们进行了递增操作 (例如,a++)。

Java 原始类型有默认值,但正如下面的某个用户评论所述:

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


23
也许 "int b = 0;" 是 "声明和初始化"。 - Arun
对于未来的访问者... 当可能未初始化的变量是类成员时,还请参阅Java中的默认值和初始化。链接 - jww
4
有人能解释一下为什么会出现这种情况吗?因为原始数据类型不能有空值,它们的默认值是0,为什么会显示未初始化的错误? - Srujan Barai
6
当作为类成员声明时,它们的默认值为零。局部变量没有默认值。 - user207421
如果“a”是一个泛型呢? - Veco

99

本地变量不会获得默认值。如果没有通过某些方式分配值,它们的初始值未定义。在使用本地变量之前,必须对其进行初始化。

在类级别(作为成员,即字段)和方法级别声明变量时存在很大的区别。

如果在类级别声明字段,它们将根据其类型获得默认值。如果在方法级别或块级别(即任何代码内部{})声明变量,则不会获得任何值,并且保持未定义状态,直到它们通过某种方式获得一些初始值,即分配一些值给它们。


9
如果它们被声明为类的字段,那么它们将真正用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 这一行。


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

5

你已经声明了它们,但是没有用一个值初始化它们。添加类似这样的内容:

int a = 0;

5
您已经声明了它们,但尚未初始化。
int a; // declaration, unknown value
a = 0; // initialization
int a = 0; // declaration with initialization

3

您声明了变量但没有为它们提供初始值-因此,它们是未初始化的。尝试像这样做:

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

同时警告信息应该消失。


3

既然没有其他答案引用过Java语言标准,我决定自己写一篇答案:

在Java中,默认情况下,局部变量不会被初始化为特定值(与类的字段不同)。从语言规范中可以读取到以下内容 (§4.12.5):

在使用之前必须显式地给局部变量(§14.4、§14.14)赋值以确定其值,可以通过初始化(§14.4)或赋值(§15.26)的方式进行验证,这遵循确定性分配规则 (§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是否根据局部变量初始化规则进行了初始化,并根据情况做出反应(例如显示编译错误)。


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可能未初始化”的错误。虽然人们可能认为在for循环内部变量a已经被“初始化”了,但编译器并不这样认为。如果arr.length的值是0,那么for循环根本不会执行。因此,编译器会给出variable a might not have been initialized来指出潜在的危险,并要求您初始化该变量。
为了防止这种错误,只需在声明变量时进行初始化即可。
int a = 0;

2

你在方法的开头声明了它们,但你没有对它们进行初始化。初始化是将它们设置为一个值,比如:

int a = 0;
int b = 0;

2

假设在循环中x[l]既不是0也不是1,那么a和b将永远不会被赋值,并且具有未定义的值。你必须初始化它们,例如将它们都赋值为0。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接