为什么局部变量没有在Java中初始化?

2022-08-31 09:29:42

Java的设计者认为局部变量不应该被赋予默认值,这有什么原因吗?说真的,如果实例变量可以被赋予默认值,那么为什么我们不能对局部变量做同样的事情呢?

这也会导致问题,如这篇博客文章的评论中所述:

好吧,当尝试在最终块中关闭资源时,此规则最令人沮丧。如果我在尝试中实例化资源,但尝试在最终关闭它,我会得到这个错误。如果将实例化移到 try 之外,则会收到另一个错误,指出它必须在 try 中。

非常令人沮丧。


答案 1

声明局部变量主要是为了进行一些计算。因此,程序员决定设置变量的值,它不应该采用默认值。

如果程序员错误地没有初始化局部变量,并且它采用默认值,则输出可能是某个意外值。因此,对于局部变量,编译器将要求程序员在访问变量之前使用某个值对其进行初始化,以避免使用未定义的值。


答案 2

您链接到的“问题”似乎正在描述这种情况:

SomeObject so;
try {
  // Do some work here ...
  so = new SomeObject();
  so.DoUsefulThings();
} finally {
  so.CleanUp(); // Compiler error here
}

评论者的抱怨是编译器在本节中的行犹豫不决,声称这可能是未初始化的。然后,注释提到了编写代码的另一种方法,可能是这样的:finallyso

// Do some work here ...
SomeObject so = new SomeObject();
try {
  so.DoUsefulThings();
} finally {
  so.CleanUp();
}

注释者对该解决方案不满意,因为编译器随后说代码“必须在尝试范围内”。我想这意味着一些代码可能会引发不再处理的异常。我不确定。我的代码的两个版本都不处理任何异常,因此第一个版本中与异常相关的任何内容在第二个版本中的工作方式都应相同。

无论如何,第二个版本的代码是正确的编写方式。在第一个版本中,编译器的错误消息是正确的。该变量可能未初始化。特别是,如果构造函数失败,则不会初始化,因此尝试调用 将是错误的。始终在获取该部分完成的资源输入该部分。soSomeObjectsoso.CleanUptryfinally

初始化后的 - 块仅用于保护实例,以确保无论发生其他情况如何,它都会被清理。如果还有其他需要运行的东西,但它们与实例是否分配了属性无关,那么它们应该进入另一个 - 块,可能是包装我所展示的那个。tryfinallysoSomeObjectSomeObjecttryfinally

要求在使用前手动分配变量不会导致真正的问题。它只会导致一些麻烦,但你的代码会更好。您将具有范围更有限的变量,以及 - 不试图保护太多内容的块。tryfinally

如果局部变量具有默认值,则在第一个示例中将是 。这并不能真正解决任何问题。而不是在块中得到编译时错误,你会潜伏在那里,可能会隐藏在代码的“在这里做一些工作”部分中可能发生的任何其他异常。(或者,部分中的异常是否会自动链接到上一个异常?我不记得了。即便如此,你也会有一个额外的例外,就像真正的例外一样。sonullfinallyNullPointerExceptionfinally