未初始化的原始实例variables是否使用内存?

在Java中,是否花费内存来声明一个类级别的实例variables而不进行初始化?
例如: int i; 如果我不用i = 5;初始化它,请使用任何内存i = 5;

细节:

我有一个巨大的超类,许多不同的(不足以拥有自己的超类)子类扩展。 一些子类不使用超级类声明的每一个单一基元。 我是否可以简单地保留未初始化的这样的原语,并且只在必要的子类中初始化它们以节省内存?

所有在你的类中定义的成员都有默认值,即使你没有明确地初始化它们,所以它们会使用内存。

例如,每个int将默认初始化为0 ,并将占用4个字节。

对于class员:

 int i; 

是相同的 :

 int i = 0; 

以下是JLS关于实例variables的内容:

如果一个类T有一个实例variables的字段a,那么一个新的实例variablesa被创build并初始化为默认值 (§4.12.5),作为每个新创build的类T或任何类的对象的一部分T的一个子类(§8.1.4)。 实例variables在作为字段的对象不再被引用之后,在对象(第12.6节)的任何必要的终结完成之后,将有效地停止存在。

是的,内存分配虽然你没有分配任何价值。

 int i; 

这需要32 bit内存(分配)。 不pipe你是否使用它。

一些子类不使用super-Class声明的每一个单一基元。 我是否可以简单地保留未初始化的这样的原语,并且只在必要的子类中初始化它们以节省内存?

同样,不pipe你初始化的地方,内存分配。

只有你需要注意的是,只要find未使用的基元,并将其删除。

编辑:添加一个点,不像原始的引用默认值是null ,它携带一个内存

  4 bytes(32-bit) 8 bytes on (64-bit) 

原来的问题是关于类级别variables的问题,答案是他们使用空间,但是也可以看一下方法范围的variables。

我们举一个小例子:

 public class MemTest { public void doSomething() { long i = 0; // Line 3 if(System.currentTimeMillis() > 0) { i = System.currentTimeMillis(); System.out.println(i); } System.out.println(i); } } 

如果我们看看生成的字节码:

  L0 LINENUMBER 3 L0 LCONST_0 LSTORE 1 

好的,正如我们所期望的那样,我们在代码中的第3行赋值,现在如果我们将第3行更改为(并且由于编译器错误而删除第二个println):

 long i; // Line 3 

…并检查字节码,然后没有为第3行生成。所以,答案是没有内存使用在这一点上。 实际上,当我们赋值给variables时,LSTORE只发生在第5行。 所以,声明一个未赋值的方法variables不会使用任何内存,事实上,不会生成任何字节码。 这相当于你首先分配给它的声明。

是。 在你的类中,即使你没有初始化variables,variables也会被赋值为默认值。

在这种情况下,你的intvariables将被赋值为0并且每个会占用4 bytes

Java语言规范和Java虚拟机规范都没有指定答案,因为它是一个实现细节。 事实上, JVMS§2.7特别说明 :

对象的表示

Java虚拟机没有为对象指定任何特定的内部结构。

理论上,一个符合标准的虚拟机可以使用位标志位来实现具有许多字段的对象,以标记哪些字段已经被设置为非默认值。 最初没有字段将被分配,标志位将全部为0,并且对象将是小的。 当一个字段第一次被设置时,相应的标志位将被设置为1,并且该对象将被resize以为其腾出空间。 [垃圾收集器已经提供了暂时停止运行代码的必要机制,以便在堆周围重新分配活动对象,这将是调整它们的大小所必需的。]

在实践中,这不是一个好主意,因为即使节省了内存,也是复杂而缓慢的。 访问字段需要暂时locking对象以防止由于multithreading造成的损坏; 然后读取当前的标志位; 并且如果该字段存在,则计数设置的比特以计算所需字段相对于对象的基础的当前偏移量; 然后读田地; 并最终解锁对象。

所以,没有通用的Java虚拟机做这样的事情。 一些拥有大量字段的对象可能会从中受益,但即使他们也不能依赖它,因为它们可能需要在不这样做的普通虚拟机上运行。

当一个对象首次被实例化时,为所有字段分配空间的平面布局简单而快速,这是标准。 程序员假定对象是按照这种方式分配的,因此可以相应地devise它们的程序以充分利用它。 同样,虚拟机器devise人员也在进行优化,以便快速使用这些应用

最终,字段的平面布局是一个惯例,而不是一个规则,尽pipe你依然可以依靠它。

在Java中,当你声明一个类的属性如String str; ,你正在声明一个对象的引用,但它并没有指向任何对象,除非你影响到一个值str=value; 。 但是,正如你所猜测的那样,即使没有指向内存的地方,参考也会消耗一些内存。