2012-06-22 99 views
21
public class Foo { 
    public static void main(String[] args) { 
     float f; 
     System.out.println(f); 
    } 
} 

print语句导致以下编译时错误,Java:为什么我需要初始化一个原始局部变量?

局部变量f可能没有被初始化

如果Java基本已经有了一个default value (float = 0.0f),为什么我需要定义一个?


编辑:

所以,这个工作

public class Foo { 
    float f; 
    public static void main(String[] args) { 
     System.out.println(new Foo().f); 
    } 
} 

谢谢大家!

+6

重新编辑:是的工作,但促进本地到字段,以避免初始化可能不是一个合理的例子:-) – fvu

+1

@fvu,这是一个例子,所以它有助于某种目的。 :D – user1329572

回答

41

因为它是一个局部变量。这就是为什么它没有分配给它:

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

编辑:为什么Java引发这个编译错误? 如果我们看一下IdentifierExpression.java类文件,我们会发现这个块:

... 
if (field.isLocal()) { 
      LocalMember local = (LocalMember)field; 
      if (local.scopeNumber < ctx.frameNumber && !local.isFinal()) { 
       env.error(where, "invalid.uplevel", id); 
      } 
      if (!vset.testVar(local.number)) { 
       env.error(where, "var.not.initialized", id); 
       vset.addVar(local.number); 
      } 
      local.readcount++; 
     } 
... 

如前所述(if (!vset.testVar(local.number)) {),JDK的检查(与testVar)如果变量赋值(Vset's source code在这里我们可以找到testVar代码)。如果不是,它从properties file引发错误var.not.initialized

... 
javac.err.var.not.initialized=\ 
    Variable {0} may not have been initialized. 
... 

Source

+5

哦,哇,今天完全学到了新东西! :D – user1329572

+1

这不是真的*解释*“为什么”,是吗? – kryger

+1

@kryger请参阅编辑。 – Zakaria

5

类字段(非final无论如何)被初始化为默认值。局部变量不是。

当声明一个字段时,并不总是需要赋值。已声明但未初始化的字段将由编译器设置为合理的默认值。

所以像f

class C { 
    float f; 
} 

一个(非final)字段将在

void myMethod() { 
    float f; 
} 

被初始化为0f但局部变量f不会。

本地变量的处理方式与字段按语言不同。局部变量具有良好的生命周期,所以初始化之前的任何使用都可能是错误的。字段不那么默认的初始化通常很方便。

+1

+1,关于非'最后'位的很棒的信息! :D – user1329572

13

事实上,编译器默认值分配给您的float f,因为在这种情况下,它是一个局部变量 - 而不是一个字段:

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

2

其实局部变量都存储在stack.Hence有采取任何旧值 目前本地variable.It机会是安全原因的一大挑战。因此,java说你必须在使用之前初始化一个本地变量。

1

嗨,大家的解决方案很简单。 存储在堆内存中的值由基于编译器的数据类型初始化,但局部变量存储在堆栈内存中,因此我们必须明确地初始化它。