简要介绍
String:immutable类,类和成员变量都被声明成final,由于不可变,类似拼接、剪裁字符串等操作都会产生新的String对象。
StringBuffer:是为了解决拼接太多产生太多中间对象的问题,我们可以用append或者insert方法,把字符串添加到已有序列的末尾或者指定位置,线程安全,但是也带来了额外的开销,所以除非有线程安全的需要,不推荐它。而是推荐StringBuilder。
StringBuilder:线程不安全,减小了开销
字符串
String从原生上保证了线程安全,StringBuffer和StringBuilder底层是利用可以修改的数组(char,jdk9以后是byte)刚开始创建的长度是初始字符串长度加16,可以指定合适大小,从而避免多次扩容开销。扩容会产生多重开销,因为既要抛弃原有数组,又要创建新的数组,还要进行copy。java8会智能将String拼接字符串转换成StringBuilder,java9提供了StringContractFactory
字符串缓存
创建一个字符串时,首先检查池中是否有值相同的字符串对象,如果有则不需要创建直接从池中刚查找到的对象引用;如果没有则新建字符串对象,返回对象引用,并且将新创建的对象放入池中。但是,通过new方法创建的String对象是不检查字符串池的,而是直接在堆区或栈区创建一个新的对象,也不会把对象放入池中。
java6以后增加了intern()方法,调用这个方法后,会从字符串常量池中寻找是否有这个字符串,没有的话就是 将字符串添加进去。但是缓存存到了永生代,空间有限,很可能导致OOM。在后续版本中将缓存存放到了堆中。