Java变量可能尚未初始化

时间:2014-06-02 22:32:00

标签: java initialization

我正在研究Project Euler Problem 9,其中指出:

毕达哥拉斯三元组是一组三个自然数,a< b< c,为此,

a^2 + b^2 = c^2

例如,3 ^ 2 + 4 ^ 2 = 9 + 16 = 25 = 52。

恰好存在一个毕达哥拉斯三重态,其中a + b + c = 1000。 找到产品abc。

这是我到目前为止所做的:

class Project_euler9 {

    public static boolean determineIfPythagoreanTriple(int a, int b, int c) {
        return (a * a + b * b == c * c);
    }   

    public static void main(String[] args) {
        boolean answerFound = false;
        int a, b, c;
        while (!answerFound) {
            for (a = 1; a <= 1000; a++) {
                for (b = a + 1; b <= 1000; b++) {
                    c = 1000 - a - b;
                    answerFound = determineIfPythagoreanTriple(a, b, c);
                }
            }
        }
        System.out.println("(" + a + ", " + b + ", " + c + ")");
    }
}

当我运行我的代码时,我收到此错误:

Project_euler9.java:32: error: variable a might not have been initialized
        System.out.println("The Pythagorean triplet we're looking for is (" + a + ", " + b + ", " + c + ")");

注意:我的每个变量(a,b和c)都有不同的行号。

我认为当我将a,b和c声明为整数时,如果未分配,默认值为0。

即使不是这种情况,它看起来像是他们所有都被分配了,所以我对这个错误感到有点困惑。

为什么会这样?

7 个答案:

答案 0 :(得分:7)

实例变量(在您的情况下,它们将是整数)被分配给0为默认值。局部变量 (From Java Docs)

如果未输入循环,则您的变量不会被初始化,这是导致错误的原因。

您可以做的是在声明时初始化

int a=0, b=0, c=0;

答案 1 :(得分:5)

你的问题就在这一行:

System.out.println("(" + a + ", " + b + ", " + c + ")");

位于while (!answerFound) {...}循环之后。编译器认为可能存在一个或多个变量abc未初始化的情况。

使用此行:

int a=0, b=0, c=0;

在声明变量时,以便在声明时初始化它们,并且错误应该消失。

答案 2 :(得分:3)

在声明局部变量之后,在方法的开头执行此操作:

a = b = c = 0;

该错误基本上表明Java无法确定变量在到达System.out.println()时是否分配了值。请记住:在Java中,只有属性具有默认值,所有局部变量必须在某些时候显式初始化。

答案 3 :(得分:3)

你的想法是对的:

你在哪里:

  • 是的,未初始化的变量可以由编译器赋值,但是a)它被认为是坏样式,b)你不应该依赖它,c)那不适用于局部变量(如方法中声明的那样) )

你错了:

  • 本地变量未分配默认值,仅分配实例变量。

供参考,请查看The docs

  

默认值

     

声明字段时并不总是需要指定值。   声明但未初始化的字段将设置为a   编译器合理默认。一般来说,这个默认值   将为零或null,具体取决于数据类型。依靠这样的   但是,默认值通常被认为是错误的编程   风格。

     

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

     

数据类型默认值(对于字段)
  字节0
  短0   int 0
  长0L
  浮点数0.0f
  double 0.0d
char'\ u0000'
字符串(或任何对象)null
  布尔值假

     

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

答案 4 :(得分:1)

在方法中声明local variables时,必须在使用它们之前为它们分配值。

答案 5 :(得分:1)

必须确信Java编译器在我们到达HERE行时,可以证明abc已设置为某种内容:

   boolean answerFound = false;
   int a, b, c;
   while (!answerFound) {
       for (a = 1; a <= 1000; a++) {
           for (b = a + 1; b <= 1000; b++) {
               c = 1000 - a - b;
               answerFound = determineIfPythagoreanTriple(a, b, c);
           }
       }
   }
   // HERE

从编译器的角度来看,如果循环执行了零次,那么它将在没有变量初始化的情况下到达HERE;因此,你不能使用它们。 我们知道这是不可能的,因为我们知道answerFound已初始化为false,因此循环将至少执行一次,并且每个{{1} }循环至少执行一次。但是语言必须有一致的规则来确定哪些程序合法,哪些程序不合法;为了避免过于复杂,编译器不需要进行必要的推断,以证明始终初始化forab 。我没有详细看过实际的“明确分配”规则,但我认为它们已经相当复杂了。

所以即使你知道变量将被初始化,你也无法说服编译器。因此,只要在声明它们时初始化它们。

c

顺便说一下,由于int a = 0, b = 0, c = 0; 之外 while次循环,当for变为answerFound时,此代码不会立即退出。它仍然执行true循环直到它们完成,然后才进行测试以查看是否离开for循环。你需要解决这个问题。

P.S。如果你想作弊,请注意每个毕达哥拉斯三元组的形式为 a = m 2 - n 2 b = 2mn < / em>, c = m 2 + n 2 ,对于某些 m n 。实际上,你可以在没有计算机的情况下使用代数得到答案。但是继续完成你开始的课程 - 这是很棒的练习。

答案 6 :(得分:0)

正如其他人所指出的那样,到a, b, c时,您的变量System.out.println可能尚未初始化。有几种方法可以避免这种情况。

初始化变量显式,所以:

int a = 0;

使用 do ... while 循环,确保循环至少运行一次,所以:

do {
    [...]
} while (!answerFound);

使用循环范围的变量,避免使用本地范围的变量,因此:

for (int a = 1; a <= 1000; a++) {
    [...]
}