总结:本小节讲述了Java的内存分配机制以及各种数据结构所使用的内存量。
重点:
1. 计算机中的电路很大一部分的作用就是帮助程序保存一些值并在稍后取出它们。
2. 计算机上的Java对内存的使用经过了精心的设计(程序的每个值在每次运行时所需的内存量都是一样的),但实现了Java的设备非常多,而内存的使用是和实现相关的。
3. 原始数据类型的常见内存、需求见算法(第4版)-1.1.2 原始数据类型与表达式。
4.
· 对象本身的开销:16字节
· 对象的引用(内存地址):8字节
· 一般内存的使用都会被填充为8字节(64位计算机中的机器字)的倍数
一个Integer对象:24字节(16字节的对象开销,4字节用于保存它的int值,4个填充字节)
一个Date对象:32字节(16字节的对象开销,3个int实例变量各需4字节,以及4个填充字节)
一个Counter对象:32字节(16字节的对象开销,8字节用于它的String型实例变量(一个引用),4字节用于int实例变量,以及4个填充字节) // 为何不用加上String型实例变量的引用指向的对象所占用的内存?
5.
· 嵌套的非静态(内部)类,例如我们的Node类,还需要额外的8字节(用于一个指向外部类的引用)
一个Node对象:40字节(16字节的对象开销,指向Item和Node对象的引用各需8字节,另外还有8字节的额外开销)
一个含有N个整数的基于链表的栈:32 + 64N字节(Stack对象的16字节的开销,引用类型实例变量8字节,int型实例变量4字节,4个填充字节,每个元素需要64字节,一个Node对象的40字节和一个Integer对象的24字节)
6.
· 数组需要4字节保存长度
· 一个数组一般需要24字节的头信息(16字节的对象开销,4字节用于保存长度以及4填充字节)
一个含有N个int值的数组:24 + 4N字节(会被填充为8的倍数)
一个含有N个double值的数组:24 + 8N字节
一个含有N个Date对象的数组:24字节(数组开销)加上8N字节(所有引用)加上每个对象的32字节,总共(24 + 40N)字节。
一个M * N的double类型的二维数组:24字节(数组的数组的开销,没打错)加上8M字节(所有元素数组的引用)加上24M字节(所有元素数组的开销)加上8MN字节(M个长度为N的double类型的数组),总共(8MN + 32M + 24) ~ 8MN字节。
7. 对象所表示的字符串由value[offset]到value[offset + count - 1]中的字符组成。
8. 一个长度为N的String对象:40字节(String对象本身)加上(24 + 2N)字节(字符数组),总共(64 + 2N)字节。
9. 当你调用substring()方法时,就创建了一个新的String对象(40字节),但它仍然重用了相同的value[]数组,因此该字符串的子字符串只会使用40字节的内存。
含有原始字符串的字符数组的别名存在于子字符串中,子字符串对象的偏移量和长度域标记了子字符串的位置。
换句话说,一个子字符串所需的额外内存是一个常数,构造一个子字符串所需的时间也是常数,即使字符串和子字符串的长度极大也是这样。
10. 在递归程序中创建数组或是其他大型对象是很危险的,因为这意味着每一次递归调用都会使用大量的内存。