【问题标题】:Default Primitive Values in Java - Memory Allocation?Java中的默认原始值 - 内存分配?
【发布时间】:2014-12-12 06:25:06
【问题描述】:

我搜索了互联网,但没有找到满意的答案。在本地化实例中,如果我有代码:

public static void main (String args[])
{
    int x;
    System.out.println(x);
}

...它不会编译,因为 Java 编译器会警告我 x 应该被初始化。我明白了。

我的问题是,Java 真的会为整数 x 留出 4 个字节的内存吗?如果是这样,它会清除那块内存吗?它是否将其定义为 NULL(我不这么认为,因为 NULL 和 int 是不兼容的类型)?还是int x 的内存地址仍然保留最后存储在内存中的值,还是x 只是简单地“没有值”?

我知道以上内容在 C 中有效,而在 C 中,它只会打印出该内存块中的任何内容。我想知道 Java 是如何处理这个问题的。

===编辑===

好的,好的。出于某种原因,我的基本编程知识完全不在我的脑海中,因为当程序无法编译时,内存分配问题是无关紧要的,正如发布答案的两位成员所指出的那样。 (提示脸)

如果我有代码怎么办:

public static void main (String args[])
{
    int x;
}

那么整数x在内存中是如何解析的呢?

【问题讨论】:

  • 如果你把 x 声明放在 main 之外(并使其成为静态),它将编译并且 x 仍将未初始化。它应该打印 0。
  • 如果程序一开始没有编译,你如何理解程序如何在内存中分配变量?
  • 如果是局部变量,必须初始化,如果不是局部变量,不指定会自动初始化为0。

标签: java memory default default-value


【解决方案1】:

这不是警告;这是一个编译器错误。该代码不会编译,因此不会生成字节码。是否留出内存的问题无关紧要,因为没有程序可以运行。

但是,如果x 变量不是本地变量,那么Java 将分配一个默认值0

Section 4.12.5 of the JLS 状态:

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

  • 每个类变量、实例变量或数组组件在创建时都会使用默认值进行初始化(第 15.9 节、第 15.10.2 节):

    • 对于byte类型,默认值为0,即(byte)0的值。

    • 对于short类型,默认值为0,即(short)0的值。

    • 对于int类型,默认值为0,即0。

    • 对于long类型,默认值为0,即0L。

    • 对于float类型,默认值为正零,即0.0f。

    • 对于double类型,默认值为正零,即0.0d。

    • 对于char类型,默认值为空字符,即'\u0000'。

    • 对于布尔类型,默认值为false。

    • 对于所有引用类型(第 4.3 节),默认值为 null。

  • 每个方法参数(第 8.4.1 节)都初始化为方法调用者提供的相应参数值(第 15.12 节)。

  • 每个构造函数参数(第 8.8.1 节)都被初始化为类实例创建表达式(第 15.9 节)或显式构造函数调用(第 8.8.7 节)提供的相应参数值。

    李>
  • 异常参数(第 14.20 节)被初始化为表示异常的抛出对象(第 11.3 节,第 14.18 节)。

  • 在使用局部变量(§14.4、§14.14)之前,必须通过初始化(§14.4)或赋值(§15.26)明确地赋予一个值,这种方式可以使用明确分配规则(§16(明确分配))。

【讨论】:

  • 但是留出内存的问题是相关的,因为如果稍后在方法中你在访问它之前为该变量赋值,它将通过编译。
  • 值得指出的是:即使代码编译通过,JVM也不是需要分配内存的。如果原始变量始终是本地的并且有一个空闲寄存器,那么高效的 JVM 根本不会分配任何东西。
  • @Eran 当然,如果程序编译,有关为int 分配内存的问题将是相关的。
【解决方案2】:

鉴于您的问题是:

  1. [W]Java 真的会为整数 x 留出 4 个字节的内存吗?
  2. 如果是这样,它会清除那块内存吗?

你要的答案在JLS 4.12.3.8

局部变量声明语句可能包含初始化变量的表达式。但是,在执行声明它的局部变量声明语句之前,不会初始化具有初始化表达式的局部变量。 (明确赋值规则(§16(Definite Assignment))防止局部变量的值在被初始化或以其他方式赋值之前被使用。)当块的执行或执行时,局部变量实际上不再存在。 for 语句完成。

所以答案是:

  1. 也许吧。该值将存储在某处
  2. 是的。 JLS 不允许使用未初始化的值。

在分配之前,局部变量不会发生任何事情。但是,在分配之前无法使用该值,因此您永远不能使用未初始化的值。在初始化时,必须使用某种存储位置(显然)。但是,JLS 不需要 JVM 分配内存。

是否分配内存将在运行时根据执行上下文、是否需要将值压入堆栈帧以进行方法调用、未使用的 CPU 寄存器是否可用等来确定。幼稚的 JVM 实现可能只是总是分配内存,但这会很慢,因此我希望大多数现实世界的 JVM 会尝试更优化的东西。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-05-07
    • 1970-01-01
    • 2019-12-29
    • 2015-05-27
    • 1970-01-01
    • 2019-10-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多