为什么局部变量(包括原语)必须始终在 Java 中初始化?
为什么局部变量(包括原语)必须始终在 Java 中初始化?为什么同样不适用于实例变量的情况?
为什么局部变量(包括原语)必须始终在 Java 中初始化?为什么同样不适用于实例变量的情况?
基本上,在读取变量之前要求为其赋值是一件好事。这意味着你不会不小心读到你不打算读的东西。是的,变量可以有默认值 - 但是如果编译器能够捕获您的错误,如果它可以证明您正在尝试读取可能尚未分配的内容,那么编译器不是更好吗?如果要为局部变量指定默认值,则始终可以显式分配该值。
现在,这对于局部变量来说很好 - 但是例如静态变量,编译器无法知道调用方法的顺序。属性“setter”是否会在“getter”之前被调用?它没有办法知道,所以它没有办法提醒你注意危险。这就是为什么默认值用于实例/静态变量的原因 - 至少这样你会得到一个已知值(0,false,null等),而不仅仅是“当时内存中发生的任何事情”。(它还消除了读取未明确擦除的敏感数据的潜在安全问题。
最近有一个关于C#的问题... - 也阅读那里的答案,因为它基本上是一回事。您可能还会发现埃里克·利珀特(Eric Lippert)最近的博客文章很有趣。它至少在同一区域,即使它的推力有些不同。
在 Java 中,如果类和实例变量未手动初始化,则它们将采用缺省值(null、0、false)。但是,局部变量没有默认值。除非为局部变量赋值,否则编译器将拒绝编译读取它的代码。恕我直言,这导致了一个结论,即在声明时用一些默认值(如null,这可能会导致以后的NullPointerException)初始化局部变量实际上是一件坏事。请考虑以下示例:
Object o;
if (<some boolean condition>)
o = <some value>;
else
o = <some other value>;
System.out.println(o);
使用 null 初始化 是完全不必要的,因为 Java 编译器在编译时会检查任何代码路径在读取变量之前是否初始化(使用 null 或某些非 null 值)。这意味着,如果您要注释掉上述代码片段中变量的两个初始化中的任何一个,编译器将拒绝编译该行。o
o
System.out.println(o);
o
这适用于Java,也许仅适用于Java。我不了解像C#这样的语言。然而,在旧的C(也许C++)中,仍然建议在声明变量AFAIK时始终初始化变量。这种“老派”编程语言可能是原因,总是初始化变量的建议在关于Java等现代语言的书籍和讨论中弹出,编译器跟踪变量是否已初始化。