String、stringBuffer、stringBuilder详解
一、三者共同点
三者共同之处是:
- 都是字符串,底层都是通过char[] 数组实现的。
- 都是final类,不允许被继承。
二、三者的区别
1.String的特点
首先,String是不可变字符串,而stringBuffer和stringBuilder都是可变的字符串。String的不可变特性是因为,首先,String的底层是用一个final char value[]的数组修饰的,final修饰就意味着这个引用数据类型的地址引用不可变,而且,他的本质又是一个数组,而数组的特点就是长度不可变,以上两点共同导致了他的不可变特性。这就导致每次对String的操作都会生成新的String对象,不仅效率低下,而且还会浪费大量的内存空间。
2.StringBuffer和StringBuilder的特点
stringBuffer和stringBuilder都继承了AbstractStringBuilder,但String没有。所以stringBuffer和stringBuilder的底层都使用了AbstractStringBuilder父类中的char[] value数组用于存储有效数据和int count来记录有效数据的个数。由于value数组的实际长度往往是要大于有效数据的个数的,所以当再次往里面添加字符的时候,如果value数组中还有剩余空间,就直接在后面存入新的字符,如果value数组中无剩余空间,此时底层就会调用扩容函数进行数组扩容,然后把原来数组中的数据拷贝到新数组中,并将value数组的地址引用指向新数组。
3.StringBuffer和StringBuilder的区别
StringBuffer是JDK1.0出现的,所以方法大多使用synchronized进行修饰,线程安全但是效率低。而StringBuilder是JDK1.5出现的,方法上没有synchronized关键字,所以效率高但是线程不安全。
三、String s 和 new String()的区别
String str = “LYQ” 对象在常量池:
首先会在常量池中查找有没有“LYQ”这个对象,如果有,就让str指向那个"LYQ"对象;如果没有,就先在常量池中新建一个“LYQ”对象,然后让str指向常量池中新建的那个"whx"对象。
String str = new String(“LYQ”) 对象存储在堆里面:
是在堆中创建对象"LYQ",然后在栈中创建用于存储"LYQ"这个对象内存地址的变量str。