String
String类在Java中用来操作字符串。我们先来简单看一看String类的源码
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence
我们发现,String类被声明为了final。表示String类不能被继承。
底层存储的数据结构:
private final char value[];
底层使用char类型数组存储数据,该数据被final修饰,表示其一旦初始化,里面的是就不能再变了。所以这就导致了,每次对String的操作都会生成新的String对象,这样不仅效率低,而且还会浪费大量的空间。
举一个简单的例子:
String s7 = new String("abc");
其在内存中的结构应为:
当我们将s7重新赋值s7 = "efg"
时,此时s7并不指向0x123这个位置,而是重新指向了一个位置。
String的不可变性体现在:
1、当对String类型的字符串进行拼接操作时,需要指定区域重新赋值,不能在原有的基础上进行修改
2、当对字符串重新赋值以后,需要重新指定一个内存区域,不能在原有的基础上进行修改。
3、当调用String的replace()方法时,也需要重新指定内存区域进行赋值。
String s1 = “abc” 和 String s1 = new String(“abc”)的区别
String s1 = "abc"是通过字面量的方式给s1赋值,此时的字符串值声明在字符串常量池中,且字符串常量池中不会存储相同内容的字符串。
String s1 = new String(“abc”)是通过new的方式,创建字符串对象的,此时会在堆中开辟一个空间存储一个地址值,该地址指向字符串常量池中的“abc”
StringBuffer
StringBuffer底层是创建了一个容量为16的char[]型数组。StringBuffer是可变的。且是线程安全的可变字符序列。
即StringBuffer每次对对象本身进行操作,不产生新的对象。StringBuffer是线程安全的
每个StringBuffer对象都有一定的缓冲区容量,当字符串大小没有超过容量时,不会分配新的容量,当字符串大小超过容量时,会自动增加容量
StringBuilder
StringBuilder和StringBuffer一样,都是可变字符序列,但是StringBuilder线程不安全。