理解String 是怎么占用内存的
来看一个每个String对象的各个属性,一个String包括如下的属性:
- 一个char数组(是个独立的对象用来存储字符串中的字符)
- 一个int 的offset属性(偏移量,用来指出字符串是从char数组中第几个字符开始的)
- 一个int 的count属性(字符串的长度)
- 最后一个int的hash属性(用来存储hashCode的值)
也就是说,即使一个String不包含任何字符,也需要在数组的引用上面消耗4个字节,再加上3个int类型的属性,3*4=12字节,加上对象头的8个字节,以上一共24个字节(目前还不需要加上填充字节)。然后,一个char数组的对象头需要12个字节,加上4个填充字节,一个空的String 消耗了40字节。
如果String 包含了17个字符,那么String 对象本身需要24个字节,但是现在17个字符的char数组要需12字节 加上 17*2=34字节,12+17*2=46字节,46不是8的倍数,加上填充字节46+2=48字节,那么17个字符的字符串会用到48+24 = 72 字节,可以看到在C语言中占据18个字节的String 在JAVA中占据了72个字节。
注:开发环境:jdk 1.6 系统:32位
子字符串的内存消耗
你可能会感到奇怪为什么字符串会有一个offset的属性和count属性。为什么char数组中的字符直接对应整个字符串呢?是这样的,当你创建一个子字符串,新创建的子字符串的char数组其实是指向的父字符串的char数组的,也就是父子字符串共享一个char数组。(但是他们有不同的offset和count)。这是一件好事还是坏事依赖于你怎么用:
- 如果在创建完子字符串之后还需要用到父字符串的话,你可以省了些内存。
- 如果创建完子字符串之后就不再需要用到父字符串的话,那么就浪费了内存
- 参考文档: JAVA对象是如何占用内存的 http://www.cnblogs.com/niurougan/p/4196057.html ;