我需要存储大量日期数据(可能足够大以至于堆空间的使用量是一个问题,因此请不要谈论过早优化),我想知道是否有必要使用某种原始表示形式来代替java.util.Date(或其他现有的Date类)。 我知道我可以进行一些分析来尝试一下,但是是否有人知道单个Date对象使用多少字节的内存?
我的第一反应是,Date类所占用的内存开销非常小。检查源代码后发现,该类只包含一个实例字段(名为“milliseconds”的long类型)。这意味着日期对象的大小是一个long类型加上一个Object实例的大小,也就是非常小。
然后我找到了这段代码,它创建了数千个对象来确定对象的大小。它指出java.util.Date对象的大小为32个字节。与仅将日期存储为long相比(它的内部实际上就是这样实现的)——long占8个字节,因此你需要为方便地拥有日期对象付出四倍的代价。
然而,创建对象的开销并不是非常高。因此,如果你真的很担心空间问题,那么就将日期存储为long型,并在需要时创建一个Date对象。
使用原始类型long?
它不是一个对象,所以占用更少的空间,日期可以表示为一个long值。当您想要存储日期并且使用更少的内存时,然后在Date和long之间进行相互转换。
如同这里所回答的:
回答这个问题最简单的方法是查看java.util.Date
的源代码。
它只有两个非静态字段(Java 1.7.0_55):
private transient long fastTime;
private transient BaseCalendar.Date cdate;
long
的内存大小为8字节,cdate
是一个对象引用,其大小为4字节。因此总共占用12字节。
如果实例化cdate
可能需要额外的字节内存,但是如果你查看构造函数,有时它甚至不会被触及,在其他情况下,它将在构造函数结束时被null
,因此最终结果也是12字节。
这仅适用于创建一个Date
。如果您对Date
调用方法(例如Date.toString()
),那么将创建并将对象存储到cdate
字段中,该对象不会被清除。因此,如果您在Date
上调用某些方法,则其内存使用量将增加。
注意:在64位JVM上,对象引用可能为64位长,这种情况下,内存使用量将为16字节。
注意#2:还要注意,这仅是Date
对象本身的内存使用量。很可能您会将其引用存储在其他类的数组、列表或字段中,这将需要额外的4个字节(或者在64位JVM上可能需要8个字节)。
Object overhead: 8 bytes => 8 bytes
+ 1 long fastTime: 8 bytes => 16 bytes
+ 1 reference cdate: 4 bytes => 20 bytes
Rounded up to nearest multiple of 8 => 24 bytes
java.util.Date对象可以用一个长整型值来表示,而长整型值是8个字节的,范围为-2^63到(2^63)-1