【问题标题】:Java: Why am I required to initialize a primitive local variable?Java:为什么我需要初始化一个原始局部变量?
【发布时间】:2012-06-22 23:40:42
【问题描述】:
public class Foo {
    public static void main(String[] args) {
        float f;
        System.out.println(f);
    }
}

打印语句导致以下编译时错误,

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

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


编辑:

所以,这行得通

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

谢谢大家!

【问题讨论】:

  • 重新编辑:是的,可行,但将本地提升到字段以避免初始化可能不是一个合理的例子:-)
  • @fvu,这是一个例子,所以它有一些用途。 :D

标签: java primitive


【解决方案1】:

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

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

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

【讨论】:

  • 这并没有真正解释“为什么”,是吗?
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

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

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

    所以像f这样的(非final)字段

    class C {
      float f;
    }
    

    将被初始化为0f,但局部变量f

    void myMethod() {
      float f;
    }
    

    不会。

    语言对局部变量的处理与字段不同。局部变量的生命周期范围很广,因此在初始化之前的任何使用都可能是一个错误。字段没有,因此默认初始化通常很方便。

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        【解决方案5】:

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

        【讨论】:

          猜你喜欢
          • 2015-08-29
          • 1970-01-01
          • 2010-09-29
          • 1970-01-01
          • 1970-01-01
          • 2018-06-11
          • 2014-06-20
          • 1970-01-01
          相关资源
          最近更新 更多