依赖默认字段初始化 - 编程风格不好吗?

Relying on default field initialisation - is bad programming style?

我得到了一个 link 官方 oracle 文档:https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html

据说在哪里:

Default Values

It's not always necessary to assign a value when a field is declared. Fields that are declared but not initialized will be set to a reasonable default by the compiler. Generally speaking, this default will be zero or null, depending on the data type. Relying on such default values, however, is generally considered bad programming style.

我想强调这部分:

Relying on such default values, however, is generally considered bad programming style.

但是,天啊,我想说,这是语言规范的一个基本部分,知道实例变量具有默认值。为什么这是一个 糟糕的编程实践 如果它甚至在 Java SE 库源代码中被广泛使用?

简单:依赖默认值无法传达意图。

您真的希望该字段以 0 开头,还是您忘记 赋值?!

当然,空引用是您需要 运行 进入空指针异常的两件事的一半。

最后,使用默认值意味着您有非最终字段。尽可能避免。

唯一的反驳论点是:为什么要写下你不必写的东西?但我认为列出的缺点强调了这一点,因此将 0 显式分配给一个字段比将它留给编译器要好。

Why on earth this is a bad programming practice

这个想法是,如果您依赖默认值,那么如果您故意将其保留为默认值,那么任何阅读代码的人都不会立即清楚,或者您只是 忘记赋值了

...if it is widely used even in Java SE libraries source code??

Java 源代码并不是您真正应该依赖的示例编码实践示例。在很多情况下都会违反此类规则(有时是故意为了小的性能改进,有时是无意或因为公认的风格多年来发生了变化。)

引用的文字是:

"Relying on such default values, however, is generally considered bad programming style."

愤世嫉俗:"it is generally considered that" 通常表示作者没有尝试为所呈现的陈述找到权威来源。

在这种情况下,断言显然是有问题的。证据:5 个中有 5 个 Java 采样的样式指南没有说明您是否应该或应该依赖默认值:

(请注意,我的抽样方法是查看 "java style guide" 的前 5 个不同的 Google 搜索结果。然后我在每个文档中搜索 "default" .这不是一个彻底的分析,但它可以说明我的观点。)


好的。那么它真的有助于 Java 代码的可读性吗?

这是有争议的。

一方面,未了解默认初始化的新手 Java 程序员可能对零或空值的来源感到困惑。但是,如果他们费心去寻找一个显式初始化并发现没有,这应该足以让他们阅读教程或书籍来了解默认初始化。 (你会希望的!)

另一方面,我们通常不希望新手 Java 程序员维护生产代码库。对于有经验的 Java 程序员来说, 冗余 初始化不会提高可读性。它(充其量)是噪音。

在我看来,通过字段的冗余初始化实现的唯一一件事就是向代码的未来 reader 发出信号,表明您有 想法关于初始值。 (正如@GhostCat 所表达的,默认初始化不传达意图。)

但反过来如果我是那个reader,我就不一定相信代码作者的想法了。所以这个"signal"的价值也是有问题的


可靠性呢?

在Java中没有区别。 JLS 指定 默认初始化 确实 发生在字段上。反之,对于局部变量,尝试使用未明确初始化的变量是编译错误。

简而言之,未显式初始化的变量的运行时行为是完全可以预测的。

相比之下,在 C 或 C++ 等可能无法初始化变量的语言中,行为是 未指定的,并且可能导致崩溃以及不同平台上的行为差异。始终显式初始化变量的情况在这里更为强烈。


性能如何?

应该没什么区别。 JIT 编译器应该能够将冗余初始化和默认初始化视为相同。