java变量作用域如何确定_关于java:如何确定变量是否具有作用域和生存期?

我了解范围和生命周期是什么,以及它们有何不同:

范围:变量的可见性,即哪些代码块可以引用该变量

寿命:变量的值将在内存中保留多长时间

我的问题是:在下图中,我们是基于什么决定变量x具有生存期而不是范围的,而变量b1具有生存期却没有生存期的?

java变量作用域如何确定_关于java:如何确定变量是否具有作用域和生存期?_第1张图片

有关Java范围的信息,请参阅本指南。

您不应该就Java和C提出这样的问题。创建单独的问题,每个问题都带有一种语言标签。

所有变量始终具有生存期和范围(以及类型,…)。

乔纳森说什么。 这个问题没有任何意义。 你从哪里得到这张废话的图片?

该图像的来源是什么?

@EricPostpischil只是要澄清一下。 最初的帖子已经包含指向图片的链接。 我的编辑使图片被显示为问题的一部分,从而使访问者无需点击链接即可查看图片。

来自大学的一门课程的@Lundin ...

在C示例中,static关键字将变量x保留在内存中,以供将来的函数调用。 但这并不意味着您可以从该函数外部访问x(就像它试图在main中那样)。 因此,您在内存中有一个变量(生命周期),但无法从函数外部访问它(无作用域)

在Java示例中,声明了对象引用,但从未创建任何对象。 因此,您可以访问引用(具有作用域),但在内存中没有对象(没有生命周期)

在Java中,Book b1;创建一个引用而不是类型为b1的对象呢?而且,如果确实创建了引用,那么即使引用尚未与引用的对象相关联,为什么不说引用具有生存期呢?引用本身不是一个在某个时间创建,与引用对象具有某些值/关联并被销毁的实体吗?

正确的是,对null的引用被推送到局部变量数组。局部变量数组具有与方法执行相同的生存期,因此,实际上空引用可能被认为具有生存期。实际对象改为进入堆,并且它们具有可变的生存期。因此,如果您这样说,那么就很难知道在哪里画线,特别是如果您考虑原始类型具有生命周期(因为它们也存在于局部变量数组中)

但同样... null既不是对象也不是类型。它是一个特殊的常数。所以我不会说它有正式的寿命,因为它根本不是变量

在这种情况下,null"引用"将由局部变量表条目,变量名称,索引,长度等以及局部变量数组中的常量组成。所有这些都将被硬编码到jvm字节码中

tl;博士,我确定该图片的作者没有考虑所有这些信息。正如你可能不应该大声笑

[该问题同时标有Java和C。此答案针对C。此处的信息摘自C 2011标准的草案N1570。]

变量由标识符(知道它的名称)和对象(保存其值的内存中的存储)组成。

标识符始终具有一定范围,而对象始终具有一定寿命。 (当用malloc分配内存时,该存储具有生存期,但是没有标识符,因此名称没有作用域。)

对于变量,其标识符的范围取决于其声明在源代码中的位置?

如果声明在任何块的外部(" {"和"}"内部的一系列语句和声明),则具有文件范围,并且从声明到翻译单元末尾都可以看到标识符(预处理后的源代码)已经完成了)。

如果声明位于块内或函数定义的参数声明内(不仅仅是声明),则声明具有块范围,并且从其声明到块末尾都可以看到标识符。

如果声明位于不是定义的函数声明的参数声明中,则该声明具有函数原型范围,并且从其声明到函数声明符的末尾都可见。

除变量标识符外,还有其他标识符。功能标识符规则;结构,联合和枚举的标签;和typedef名称与变量标识符相同。对于标签(在goto语句中使用,写为label:),标识符具有函数作用域,并且在显示函数的任何位置都可见。

有四个存储期限,也称为生存期:静态,线程,自动和已分配。对象的存储期限受其标识符链接的影响,因此我们需要首先讨论链接。链接是一种使不同范围中的相同标识符引用同一对象的方法。

如果使用static声明了文件范围内的对象或函数的标识符,则它具有内部链接。内部链接意味着同一翻译单元中的任何其他声明将引用同一对象或函数。

如果使用extern声明标识符,则链接取决于是否已经存在一个在先的声明:

如果看不到先前的声明,则标识符具有外部链接。这意味着程序中的任何其他声明将引用相同的对象或函数。

如果存在在先声明,并且指定了内部或外部链接,则当前声明的链接与在先声明相同。

如果存在先前的声明,但未指定任何链接,则当前声明的链接是外部的。

如果声明的函数没有存储类说明符(typedef,extern,static,_Thread_local,auto或register),则其链接就像使用extern声明的那样(因此它遵循上述规则,取决于事先声明)。

如果在文件范围内没有存储类说明符声明对象,则其链接是外部的。

否则,该标识符没有链接,因此它的每个声明都引用一个不同的实体。这包括不是对象或函数的任何内容的标识符(例如结构标记或typedef名称),函数参数以及在函数内部声明的不带extern的变量。

现在我们可以说明存储期限的规则:

如果使用static而不是_Thread_local声明对象,则该对象具有静态存储期限,并且其生存期是程序的整个执行过程。

如果声明的对象不带_Thread_local且具有外部或内部链接,则该对象具有静态存储持续时间。

如果用_Thread_local声明对象,则该对象具有线程存储持续时间,并且其生存期是为其创建线程的整个执行。

如果声明的对象没有static且没有链接,则它具有自动存储期限。如果它不是可变长度数组,则其生存期是从执行进入其所在的块开始,直到该块的执行结束。 (请注意,调用函数会中止块的执行,但不会结束。)如果它是可变长度数组,则其生存期是从执行到达声明时开始,直到执行离开声明的范围为止。

还为malloc系列中的例程创建的对象分配了存储时间,并且存在一个临时生命周期,该生命周期适用于在表达式内创建的对象,但是由于它们与命名对象的声明无关,因此省略了对它们的讨论。

如您所见,规则有些复杂。但是,您将通过实践认识到范围和寿命。

好。

你可能感兴趣的:(java变量作用域如何确定)