“variable may not have been initialized” 的设计理念是什么?

6

众所周知,在Java中使用局部变量之前需要初始化它(参见JLS

必须在使用局部变量(§14.4、§14.14)之前,通过初始化(§14.4)或赋值(§15.26)显式地给它一个值,以便可以使用明确分配(§16)的规则进行验证。

否则会出现编译器错误:

The local variable result may not have been initialized.

这个设计决策的理由是什么?为什么编译器不会自动将声明(例如 int xdouble yString foo 等)转换为使用一些默认值(0、0.0、null)初始化的定义?这样做有什么缺点吗?

1
如果本地变量被初始化为默认值,它可能是难以发现的错误源。 - Kayaman
让编译器去做这件事,可能会将微不足道的编译时错误转化为令人讨厌的运行时错误。 - David Soroko
3个回答

6
缺点在于默认值可能不是你想要的 - 你可能只是忘记初始化你的本地变量,并且使用默认值可能会导致异常(或更糟糕的是,仍然运行,创建一些难以跟踪的错误)。 在这种情况下强制编译器错误确保你纠正问题并明确地将其分配给任何你想要的内容。
同样的论点也适用于字段,但是检查它们在读取该值之前是否已被赋值要困难得多(在每种情况下技术上不可能),因为它们可以从任何地方访问或写入。因此,在这种情况下使用默认值而不是强制执行此规则是唯一明智的方法。

2
那么实例变量在获取默认值时有什么区别?在这里,您也可能会面临“默认值可能不是您想要的 - 您可能只是忘记初始化…”的情况。 - sergeyan
@sergeyan 这是一个实际的原因 - 请参见编辑。 - Michael Berry

0

只是为了说明一下berry的用法。

int x;
float y;

y = 42/x;

String name;

print("Hello " + name);

遗憾的是,这些是那些不强制执行该策略的语言中最常见的错误之一。 请记住,默认值可能对每个变量都不同,因此将其留给开发人员来设置。


0

补充@berry120的回答 - 关于字段和变量之间的区别。

未初始化的变量

'未初始化'状态的行为与final字段或变量的行为几乎相同,除了可以重新分配值(我将引用它作为“最终行为”)。因此,在像这样的分支中不会忘记对其进行初始化:

int x;

if(condition1){
    x = 10;
} else
if(condition2){
    if( condition3 ){
        x = 20;
    }   // else branch is missing here
} else {
    x = 40;
}

所以编译器会在这里提示我一个初始化错误。为什么不使用final来达到同样的目的,并为变量设置一个默认值呢?更多的输入和冗长 + 我可能想要重新分配给这个变量。

字段的默认值

我认为对于实例变量来说,拥有一个默认值是更好的选择,因为用'final行为'来初始化变量可能会对具有许多构造函数的类造成真正的困扰。当你子类化这个类和/或使用循环引用时,它可能会变得非常麻烦...或者是一个难题:如何初始化循环依赖(相互引用的final字段)?

所以对于实例字段来说,出现'The result may not have been initialized'似乎是不切实际的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接