为什么必须在Java中初始化局部变量(包括基元)?

Gou*_*rav 53 java variables primitive-types

为什么必须在Java中初始化局部变量(包括基元)?为什么在实例变量的情况下不相同?

Jon*_*eet 67

最近有一个关于C#的问题 ...... - 在那里阅读答案,因为它基本上是一回事.您可能还会发现Eric Lippert最近的博客文章很有趣; 它至少在同一区域附近,尽管它的推力有些不同.

基本上,要求在读取变量之前为变量赋值是一件好事.这意味着你不会意外地阅读你不想要的东西.是的,变量可能有默认值 - 但是如果它能够证明你正在尝试读取可能尚未分配的东西,那么编译器是否能够更好地捕获你的bug?如果要为局部变量提供默认值,则可以始终明确指定.

现在这对于局部变量很好 - 但是例如和静态变量,编译器无法知道调用方法的顺序.在"getter"之前是否会调用属性"setter"?它无法知道,所以它无法提醒你危险.这就是为什么默认值用于实例/静态变量-至少,你会得到一个已知值(0,假,空等),而不是仅仅"不管发生什么事情是在内存中的时间." (它还消除了读取未明确擦除的敏感数据的潜在安全问题.)

  • 对象不为null.A*variable*可以为null,但不是对象.并且局部变量*没有*具有默认值...正是因为没有一个意味着你必须在读取之前给它一个有用的值.如果你想把这个值设为null,那很好......但我更喜欢编译器告诉我是否正在尝试阅读可能尚未初始化的内容...... (5认同)

quo*_*soo 8

好吧,在局部变量的情况下,很清楚"之前"是什么意思,因为声明(在方法中)和引用之间的程序流是顺序的.如果在方法之外声明的字段,编译器永远不知道将要使用哪个代码,因此它不能生成错误,因为可能某些其他方法在使用之前初始化该字段.


Sve*_*ven 8

在Java中,如果未手动初始化类和实例变量,则它们将采用默认值(null,0,false).但是,局部变量没有默认值.除非为局部变量赋值,否则编译器将拒绝编译读取它的代码.恕我直言,这导致了这样的结论:在声明它时,初始化一个带有一些默认值的局部变量(如null,后面可能会导致NullPointerException)实际上是一件坏事.请考虑以下示例:

Object o;
if (<some boolean condition>)
  o = <some value>;
else
  o = <some other value>;
System.out.println(o);
Run Code Online (Sandbox Code Playgroud)

o使用null 的初始化是完全没有必要的,因为Java编译器在编译时检查任何代码路径o在读取变量之前初始化(使用null或某些非null值).这意味着,System.out.println(o);如果您要o在上面的代码片段中注释掉变量的两个初始化中的任何一个,编译器将拒绝编译该行.

这适用于Java,也许仅适用于Java.我不知道像C#这样的语言.但是,在旧的C(也许是C++)中,仍然建议在声明变量AFAIK时始终初始化变量.这种"老派"编程语言可能是这样的原因,即总是初始化变量的建议出现在书籍和有关现代语言(如Java)的讨论中,其中编译会跟踪变量是否已初始化.


Ste*_*Kuo 6

不完全正确.只有在引用时才需要初始化局部变量.如果从未引用,则局部变量可以保持未初始化.例如:

int x;  // Valid
int y;
println("y=" + y);  // Not valid since y's value has never been assigned
Run Code Online (Sandbox Code Playgroud)