Java:为什么我需要初始化一个原始局部变量?
public class Foo { public static void main(String[] args) { float f; System.out.println(f); } }
print语句导致以下编译时错误,
局部变量f可能尚未初始化
如果Java中的原语已经有一个默认值(float = 0.0f) ,为什么我需要定义一个?
编辑:
所以,这是有效的
public class Foo { float f; public static void main(String[] args) { System.out.println(new Foo().f); } }
感谢大家!
因为它是一个局部变量。 这就是它没有分配给它的原因:
局部变量略有不同; 编译器永远不会为未初始化的局部变量分配默认值。 如果无法初始化声明它的局部变量,请确保在尝试使用它之前为其赋值。 访问未初始化的局部变量将导致编译时错误。
编辑:为什么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
的源代码 ,我们可以在其中找到testVar
代码)。 如果没有,它会从属性文件中引发错误var.not.initialized
:
... javac.err.var.not.initialized=\ Variable {0} may not have been initialized. ...
资源
实际上,编译器没有为float f
分配默认值,因为在这种情况下它是一个局部变量 – 而不是一个字段:
局部变量略有不同; 编译器永远不会为未初始化的局部变量分配默认值。 如果无法初始化声明它的局部变量,请确保在尝试使用它之前为其赋值。 访问未初始化的局部变量将导致编译时错误。
类字段(无论如何都是非final
的)被初始化为默认值。 局部变量不是。
声明字段时并不总是需要分配值。 声明但未初始化的字段将由编译器设置为合理的默认值。
所以像f
in这样的(非final
)领域
class C { float f; }
将初始化为0f
但局部变量f
in
void myMethod() { float f; }
不会是。
语言区域处理的局部变量与字段不同。 局部变量具有良好的生命周期,因此在初始化之前的任何使用都可能是错误的。 字段不是这样,默认初始化通常很方便。
实际上局部变量存储在堆栈中。因此有可能为本地变量提供任何旧值。对于安全性原因来说这是一个很大的挑战。因为java说你必须在使用之前初始化本地变量。
嗨大家解决方案很简单。 存储在堆内存中的值由基于编译器的数据类型初始化,但局部变量存储在堆栈内存中,因此我们必须明确地将其初始化。