【问题标题】:Why Java initializing only class variables by default but not local variables?为什么Java默认只初始化类变量而不初始化局部变量?
【发布时间】:2014-10-26 18:06:05
【问题描述】:

我正在学习 Java 中的链表,我有三个文件 Main.javaList.javaNode.java。当我这样做时,我遇到了一个问题,为什么我应该初始化在方法中声明的局部变量而不是在类中声明的类变量。

在第一张图片中,我将 head 声明为类变量,它不会引发任何错误。

但在第二张图片中,我将 head 初始化为局部变量。现在,初始化局部变量会引发错误。

声明为类变量时有何不同?

Java 初学者。

更新:我知道如何解决这个问题,但我不清楚为什么 Java 默认只初始化类变量而不初始化局部变量。

【问题讨论】:

  • 字段变量默认初始化。这是因为这些变量需要在实例创建后就可以访问,因为只要对象处于活动状态,它们就可以访问。但是,只有在执行特定的局部范围时才需要局部变量。如果 Java 要初始化本地变量,它们要么在每次执行范围时被初始化,要么需要保存在堆栈中的某个位置。出于性能原因,我确定是这种方式
  • @AndyThomas 我不知道为什么这被标记为重复。他没有询问错误(我相信他知道如何修复)。他在问为什么会这样,这是我在 StackOverflow 上找不到的问题
  • @VinceEmigh - 很公平,这是一场艰难的比赛。重新开放。
  • 请重新格式化您的问题和标题以更好地适应情况。 “为什么 java 默认只初始化类变量而不初始化局部变量”会是一个更好的标题(取自您的更新)
  • @VinceEmigh 是的,我做到了。谢谢:)

标签: java oop


【解决方案1】:

不是原始的静态/非静态字段,例如您的Node,默认初始化为null。 原始的静态/非静态字段获取它们的默认值。

还有另一种情况,一些变量被默认初始化:当你实例化一个数组时。每个单元格代表都有默认值,关于类型:

  • 0int
  • nullInteger

但是,在局部方法中,编译器不会为局部变量分配默认值。
这就是为什么您的 IDE 会发出警告:“可能未初始化!”。

要了解原因,您可能对此post 感兴趣。

【讨论】:

  • 嗯,你的链接给了我澄清。谢谢:)
【解决方案2】:

the Java Language Specification 很好地解释了这一点(具体来说,第 4.12.5 节):

程序中的每个变量在使用它的值之前都必须有一个值:

  • 每个类变量、实例变量或数组组件在创建时都会使用默认值进行初始化(第 15.9 节、第 15.10 节):
  • 对于所有引用类型(第 4.3 节),默认值为 null。
  • 局部变量(第 14.4 节,第 14.14 节)必须在使用前明确指定一个值,通过初始化(第 14.4 节)或赋值(第 15.26 节) ),以一种可以使用明确分配规则 (§16) 进行验证的方式。

为了扩展一点,第 16 条进入了definite assignment 的规则,这是原因的关键:

每个局部变量(第 14.4 节)和每个空白最终字段(第 4.12.4 节,第 8.3.1.2 节)在对其值进行任何访问时都必须有一个明确分配的值

对于局部变量或空白最终字段 x 的每次访问,必须在访问之前明确分配 x,否则会发生编译时错误。

简单地说:Java 将为类/实例变量分配默认值,但不会为局部变量分配默认值。必须以这种方式明确地分配局部变量(通过初始化或赋值),否则会发生编译时错误(如您所见)。

如果您从另一个角度考虑,当您初始化一个包含特定字段的类时,您可能一开始并不希望将它们初始化为一个值(想想JavaBeans)。如果您在代码块中并声明一个变量,则期望开发人员在代码块中控制该对象的生命周期。

简单地声明一个变量并尝试用它做某事是没有意义的价值。

【讨论】:

  • 他已经知道了。阅读他的问题的最后一部分编辑:nvm,它被删除了。但他表示他理解它必须被初始化。他只是不知道为什么会这样
  • 我不确定您所说的“他已经知道这一点”是什么意思。 JLS 引用没有明确说明,这就是 必须初始化局部变量但不必初始化实例变量的原因。
  • “局部变量在使用前必须显式赋值”所以这就是为什么局部变量没有初始化为默认值的原因?如果他问“我为什么会收到这个错误”,那就是答案
  • 更多信息来自 JLS 的第 16 节。我已将其添加到答案中。
  • 但是你没有提到为什么。他明白会出现编译时错误,但是为什么在使用前没有初始化局部变量时会出现这种情况呢?有人可能会说“因为 java 就是这样工作的,所以在尝试使用未初始化的局部变量时会出现编译时错误”,但他正在寻找合乎逻辑的原因。在他的更新中,他说他知道如何解决它;他只是不明白为什么字段变量会被初始化为默认值而局部变量不会
【解决方案3】:

在第一种情况下,java 无法知道,当您将值分配给节点“head”时。您可以在调用“添加”之前先打个电话 第二个命令方法相同,执行顺序明确。

在每种情况下,您都应该初始化每个变量。如果我记得正确的成员变量被初始化为 null,但我不确定它是否适用于每个 jvm

【讨论】:

  • reference 字段变量被赋值为 null。 原始字段变量被初始化为它们的default values(向下滚动到默认值)
  • 这是语言规范的一部分,不是 JVM 对规范的解释。事实上,如果你显式地初始化实例变量,一个幼稚的 JVM 可能会产生更大的代码。您实际上是在要求 VM 在构造函数之前运行该类的代码。恕我直言,这是糟糕的 Java 形式。
【解决方案4】:

为什么该语言会以这种方式工作,这是因为首选的风格是延迟局部变量的声明,直到它们第一次被使用。 Java 的设计是为了让您不必在第一次使用它的地方声明变量(例如,与 JavaScript 不同,由于缺少块级范围并且由于提升,您最好声明方法或函数开头的变量),因此局部变量没有获得默认值应该不是问题。

同样对于局部变量,这个想法一定是分配默认值的价值相对较小。即使我确实想初始化一个局部变量,最好明确说明它。

当然,例如和类成员 declare-at-first-use 不适用,因为不知道什么可以调用它。如果未分配某些内容,则需要接收默认值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-29
    • 2021-03-17
    • 2016-09-07
    • 1970-01-01
    • 2011-01-06
    • 1970-01-01
    相关资源
    最近更新 更多