String, StringBuffer, StringBuilder
1.String
String具有不可变性,是固定长度的,底层是用final修饰的char型数组:
String设置为不可变原因:
1.1 运行时常量池的需要:如果常量池已存在所需string数据,就可以直接调用而不需要重新创建,从而节省了空间。
1.2 可以保证String数据的hashcode是唯一的。
1.3 String的不可变可以使得多个线程共享而不会出现问题,保证了线程安全。
1.4 平时我们需要的登录用户名,密码也不会随便被修改,从而提高了安全性。
2. StringBuffer与StringBuilder
因为String是不可变的,我们不能对它进行修改,所以提出了可供修改的StringBuffer与StringBuilder.
这两者都继承了AbstractStringBuilder类,其的底层也都是一个char型数组。但StringBuffer是线程安全的,StringBuilder不是线程安全的。
原因:
StringBuffer的源码显示:每一个方法前都有关键字synchronized修饰:
而StringBuffer没有:
关于扩容:
StringBuffer与StringBuilder的扩容机制是一样的,这里以StringBuilder为例:
首先初始化的底层数组大小默认为16;
但如果是带有参数的构造器,初始化数组的大小因为参数的长度加上16:
在添加一个数据时候,如果数据的长度能够在这个数组中放得下,则直接append。但如果大了,则需要进行扩容:
上面这个函数ensureCapacityInternal就是用来判断的,count是当前StringBuffer中数据的长度,len是添加数据的长度,两者相加表示需要的最小数组长度。
当需要的最小数组长度大于当前数组长度,则需要扩容,即生成新的数组(长度为扩容后的长度),在将原来的值赋给新数组。
扩容函数:newCapacity:
新的数组长度就是原来的长度n*2+2,但当扩容后如果仍不能满足需求,则将新的数据长度赋值为所需的最小数组长度。