【问题标题】:Variable might not have been initialized error变量可能未初始化错误
【发布时间】:2017-12-24 02:12:57
【问题描述】:

当我尝试编译时:

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

在我看来,我在方法的顶部初始化了它们。怎么了?

【问题讨论】:

    标签: java variables initialization


    【解决方案1】:

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

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

    您收到错误是因为您尚未初始化变量,但您在 for 循环中递增它们(例如,a++)。

    Java 原语具有默认值,但正如一位用户在下面评论的那样

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

    【讨论】:

    • 也许“int b = 0;”是“声明和初始化”。
    • 对于未来的访问者...当可能未初始化的变量是类成员时,另请参阅Default Values and Initialization in Java
    • 谁能解释一下这是怎么可能的,因为原语不能有空值,它们的默认值为0,为什么它显示未初始化错误?
    • @SrujanBarai 当声明为类成员时,它们的默认值为零。局部变量没有默认值。
    • 如果“a”是泛型呢?
    【解决方案2】:

    局部变量没有默认值。它们的初始值是未定义的,没有通过某种方式分配值。在你可以使用局部变量之前,它们必须被初始化。

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

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

    【讨论】:

      【解决方案3】:

      如果它们被声明为类的字段,那么它们将真正被初始化为 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

      【讨论】:

      • 静态成员可能以其他方式获取默认值。
      【解决方案4】:

      你声明了它们,但没有初始化。

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

      【讨论】:

        【解决方案5】:

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

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

        警告应该消失。

        【讨论】:

          【解决方案6】:

          由于没有其他答案引用了 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,分别)不是编译器job试图分析你的应用程序的逻辑局部变量初始化的规则也不依赖于此。编译器检查变量ab是否根据局部变量初始化规则进行初始化,并做出相应的反应例如,显示编译错误)。

          【讨论】:

            【解决方案7】:

            你声明了它们,但你没有用值初始化它们。添加如下内容:

            int a = 0;
            

            【讨论】:

              【解决方案8】:

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

              int a = 0;
              int b = 0;
              

              【讨论】:

                【解决方案9】:

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

                【讨论】:

                  【解决方案10】:

                  在使用方法块之前初始化方法块内的局部变量是一种很好的做法。这是初学者可能犯的错误。

                    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;
                  

                  【讨论】:

                    【解决方案11】:

                    您还没有初始化ab,只是声明了它们。有细微的差别。

                    int a = 0;
                    int b = 0;
                    

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

                    【讨论】:

                    • 你不能从 C++ 派生它。 Java 中的局部变量不会自动获取默认值(但如果 Java 的设计不同,则可能会有),但实例和类变量(“静态”)确实会获取默认值。
                    【解决方案12】:

                    将变量“a”设置为像这样的某个值,

                    a=0;
                    

                    声明和初始化都是不同的。

                    祝你好运

                    【讨论】:

                    • 并非如此。初始化是声明语法的可选部分。
                    猜你喜欢
                    • 2016-07-17
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多