原创地址:http://my.oschina.net/u/2323537/blog/530423
以前学java基础的时候考虑过string占多少字节,百度后有人说一个汉字占两个字节,所以一个string的字节数是可变的,遇到一个汉字+2,遇到一个字母+1。笔者对此结论严重怀疑,一个string在分配内存空间的过程中怎么可能会动态变化呢。笔者开始尝试测试string所占的字节数。
一:首先想到的是通过string的getBytes方法测试其所占长度,是否与上述结论一致。
请看下面代码:
String a="中国";
System.out.println(a.getBytes().length);
返回结果为6。
这个结果与上述结论明显有出入,一个汉字占3个字节吗?显然不是这样的,因为一个char占两个字节,char是可以存放一个汉字的。getBytes方法只是将字符串转换为字节码,其转换关系在源码中可以找到,他是使用默认字符集将string转换为byte序列的,至于为啥每个汉字在getBytes的时候是3个,还请大神指教。
二:通过outofmemory异常测试
首先我们的电脑内存空间是有限的,所以如果定义一个数组的长度过长,一定会抛出outofmemory异常,每个人的整块内存空间应该是不一样的,所以笔者先测了下自己电脑上的最大整块内存空间,经多次调试,发现内存空间大小为1365966832字节。
byte b[]=new byte[1365966832];
这是一个临界值,再加1就会抛出outofmemory异常。大概1.3个G。
同理测试,用string数组创建的话,临界值为341491708。
上面的数除以下面的数等于4!故为4个字节。
三:由于创建对象的初期,jvm虚拟机会把分配到的内存空间全部初始化为0(不包括对象头),其值为这些字段的数据类型对应的0值(引自深入理解java虚拟机),所以目前数组中的每个string还是null值(string对应的0值为null),那么根据最开始的可变理论,我们上述的结论还不够有说服力。我们开始为该数组赋值。
String str[]=new String[341491708];
for(int i=0;i<str.length;i++){
str[i]="f";
}
System.out.println(str[0]);
结果没有抛出异常,数组长度再大也可以。说明字节长度不变就是4个字节。
四.有人可能会说,这样声明的字符串是被放到常量池里了,返回的只是个引用。ok我们利用最后零散的的内存空间new字符串出来。
--------
擦擦擦,刚刚死机了,感谢oschina的自动保存功能。。。
--------
String str[]=new String[341491708];
for(int i=0;i<str.length;i++){
str[i]=new String("f");
if(i>996710){
System.out.println(i);
}
}
结果我的电脑不到100万就溢出了,换再长的字符串也一样。这里想亲手做实验的童鞋注意,之所以有个if判断才打印是因为打印很耗时,过滤掉前面没用的打印而已。
综上所述string占4字节
----------------------------------------------------割割割割割割----------------------------------------
以上论断是错的,具体原因应该与c语言的指针类型有关,现在笔者还有些东西没有想清楚,想清楚后会改,敬请期待~