String
- 被
final
修饰的类, - 是一个
Immutable
(不可变)的类,
在声明多个相同字符串的时候,只会创建一个字符串对象,创建的时候
首先会先去常量池查找,如果字符串存在就不会创建一个新的字符串
原理:
在执行String s = "a";
的时候会创建个对象
在执行s = "123456";
的时候会创建个新的对象,并不是会覆盖原来的值
实际上s
是存放在引用地址中,引用的是char value[]
数组,数组中存放变量123456
但是真的不可变么?其实我们可以通过反射来改变String中的value字段
例如:
String s = 'Hello Word';
//首先通过反射获取到String中的value字段
Field valueFieldOfString = String.class.getDeclaredField("value");
//改变value的访问权限
valueFieldOfString.setAccessible(true);
//获取到s对象上value属性的值
char[] value = (char[]) valueFieldOfString.get(s);
//改变value所引用的数组中的第5个字符(索引,角标)
value[5]='_'; //Hello_Word
这样Hello Word
就变成了Hello_Word
StringBuffer与StringBuilder
- 长度可变,实际上是基于一个可变的
char[]
数组,默认大小16
当创建StringBuffer
与StringBuilder
的时候,会去内存中创建一个存放值的空间,
当执行xxx.append("")
的操作的时候,会去开辟一个更大的空间
把原来的内容复制到新的空间当中在加上新的内容,也就是append中的内容
最后char[]
数组会指向新开辟的地址
所以无论执行多少次jvm都如上操作
所以StringBuffer
与StringBuilder
长度是可变的,它们没有被final
修饰
- 它们都继承于
AbstractStringBuilder
StringBuffer
是线程安全的,StringBuilder
是线程不安全的
应用场景:
String
- 字符串内容不发生改变时常用
- 例如,常量声明和少量的字符串拼接操作
StringBuffer
- 适用于频繁的对字符串操作的时候,并且适用于多线程的环境下
- 例如:xml解析等
StringBuilder
- 适用于频繁的对字符串操作的时候,并且适用于单线程的环境下
- 例如:sql语句拼接等
总结:
- String`的长度是不可变的,但是值是可以改变的
StringBuffer
和StingBuilder
的长度是可变的。- 如果对字符串中的内容经常进行操作,特别是内容要修改时,那么使用
StringBuffer
或StingBuilder
- 如果最后需要
String
,那么使用StringBuffer
的toString()
方法,转化成String
。