Java:为什么我需要初始化一个原始的局部变量?

时间:2012-06-22 23:40:43

标签: java primitive

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

print语句导致以下编译时错误

  

本地变量f可能尚未初始化

如果Java中的原语已经有default value (float = 0.0f),为什么我需要定义一个?


编辑:

所以,这是有效的

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

谢谢大家!

5 个答案:

答案 0 :(得分:44)

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

  

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

编辑:为什么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

答案 1 :(得分:14)

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

  

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

答案 2 :(得分:6)

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

  

声明字段时并不总是需要指定值。声明但未初始化的字段将由编译器设置为合理的默认值。

这是一个(非final)字段,如

中的f
class C {
  float f;
}

将初始化为0f,但

中的局部变量f
void myMethod() {
  float f;
}

不会。

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

答案 3 :(得分:2)

实际上局部变量存储在堆栈中。因此有可能获取任何旧值 为安全原因提出了一个很大的挑战。因为java说你必须在使用前初始化一个本地变量。

答案 4 :(得分:1)

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