1.new String的过程浅析
字符串常量是保存再常量池中的,直接通过赋值的形式的话,就会直接在常量池里找看有没有,有就直接指向这个常量
Eg:String s = “long”;
但如果是通过new关键字来创建对象的话,就会先开辟一片内存空间后,再把类里的Value指向常量池中,所以这样的两个对象的地址不同
字符串并不是由new创建的,当你写一个字符串就会被jvm创建一个Sting象
2.StringBuilder
这个类的原理其实和ArryList有异曲同工之妙,也是用一个数组来保存字符串,在调用构造方法的时候会默认创建一个你的字符串长度加16的长度的数组,用append增加字符的时候会先检查新的字符串与旧的字符串和起来的时候会不会超出数组长度,超出则调用一个方法来对数组进行扩展,会用到Arrays.copy()方法,之后用String.getChar()方法把新字符添加到旧字符数组中。所以这个类的效率主要影响在于创建数组的频率.扩展策略是指数扩展策略,原因很明显,指数增长在每次扩展后,下次都会增长的更多,这样确实超级不错,真几把聪明,16*2+2 34*2+2指数增长,为什么加二是因为如果前两个数都是0,那不这个整体都是0了,所以加二,作者真的是什么都想到了,佩服至极.
toString(),,,,,,,,,,,这个方法是new了一个String对象再把字符串传进去,这么做是为了防止影响到原本的数据
insert,,,,,,,,,,,,,,,,,最终调用的是抽象的父类的方法,具体过程是
public AbstractStringBuilder insert(int index, char[] str, int offset,int len){
判断是否超出数组长度或者下标为负数,如果是就抛异常
if ((index < 0) || (index > length()))
throw new StringIndexOutOfBoundsException(index);
判断插入位置是与要插入的长度与是否越出数组最大长度
if ((offset < 0) || (len < 0) || (offset > str.length - len))
throw new StringIndexOutOfBoundsException(
"offset " + offset + ", len " + len + ", str.length "
+ str.length);
判断空间是否足够,足够就不管,不够就扩展
ensureCapacityInternal(count + len);
调用System类的arraycopy方法把第二个value的数据复制到第一个value里这里要注意最后一个参数的意思是把第一个Value从index到count-index的字符串截取下来复制到第二个value里的index+len后面的地方
System.arraycopy(value, index, value, index + len, count - index);
下面就是把传入的Str复制到上面已经准备好的数组里去
System.arraycopy(str, offset, value, index, len);
count += len;
return this;
}
最后,java字符串也可以+=,在编译后其实也是被编译成了下面的样子
这里写一个大概过程,具体的还看不懂,应该是先new一个StringBuilder对象然后每+一个字符串就调用一次append()方法,最后调用toString()方法来还原成String类型
invokestatic java.lang.String.valueOf(java.lang.Object) : java.lang.String [20]
11 invokespecial java.lang.StringBuilder(java.lang.String) [26]
14 ldc <String "fff"> [29]
16 invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder
19 invokevirtual java.lang.StringBuilder.toString() : java.lang.String [35]
需要注意的是,只有在当String类型的变量进行运算的时候才会new一个StringBuilder对象