目录
一、共性
String、StringBuilder和StringBuffer,
都来自 java.lang 包;
数据类型都为引用数据类型;
二、实现接口
类 | 实现接口 | ||
String | Serializable | CharSequence | Comparable |
StringBuffer | Serializable | CharSequence | Appendable |
StringBuilder | Serializable | CharSequence | Appendable |
三、常用构造方式
类 | 常用构造方式 | ||
String | 常量串直接赋值 | 使用字符数组 new 对象 | 使用字符串序列 new 对象 |
StringBuffer | 使用字符串序列 new 对象 | ||
StringBuilder | 使用字符串序列 new 对象 |
public static void main(String[] args) {
//常量串直接赋值;
String str1 = "abc";
System.out.println(str1); //输出:abc;
//使用字符数组 new 对象;
char[] chars = {'a','b','c'};
String str2 = new String(chars);
System.out.println(str2); //输出:abc;
}
因为String、StringBuilder和StringBuffer都实现了CharSequence(字符串序列接口),而且三个类都有以实现CharSequence接口实现类作为构造参数的构造方法,所以这三个类可以互相构造;
public static void main(String[] args) {
//三个类相互构造;
String s = "abc";
StringBuffer sf = new StringBuffer(s);
StringBuilder sb = new StringBuilder(sf);
String str = new String(sb);
System.out.println(str); //输出:abc;
}
四、可变性
String | 不可变,字符串内容在对象创建后不会被更改,如字符串拼接会产生一个新字符串,而不是在原字符串上更改; | ||
StringBuffer | 可变,可以在原字符串上更改、拼接等;每次获取字符串都会直接使用缓存区的 toStringCache 值来构造一个字符串; | ||
StringBuilder | 可变,可以在原字符串上更改、拼接等;每次获取字符串都需要复制一次字符数组,再构造一个字符串; |
String不可变的原因
1.String在类设计上就是不可变的:String类中的字符实际保存在内部维护的value字符数组中,该数组被private修饰,使得字符串的值不能被外部获取,因此无法修改;
(此外,
String类被final修饰,表明该类不能被继承;
value字符数组被修饰被final修饰,表明value自身的值不能改变,即Value的地址值不会改变,但是地址值指向的内容可以被改变;)
2.方便实现字符串对象池:如果 String 可变, 则对象池就需要考虑写时拷贝的问题(?);
3.保障线程安全:不可变对象是线程安全的;
4.方便缓存哈希码:不可变对象更方便缓存 hash code, 作为 key 时可以更高效的保存到 HashMap 中(?);
五、线程安全性
String | 是不可变序列,线程安全; | ||
StringBuffer | 采用同步处理,大部分方法都使用了synchronized关键字,属于线程安全操作; | ||
StringBuilder | 未采用同步处理,方法没有使用synchronized关键字,属于线程不安全操作; |
六、执行效率
String | 所有涉及到可能修改字符串内容的操作都是创建一个新对象,改变的是新对象;尽量避免直接对String类型对象进行修改,因为String类是不能修改的,所有的修改都会创建新对象,效率非常低下; | ||
StringBuffer | 效率较快,但由于大部分方法都使用了synchronized关键字来保障线程安全,所以每次操作都会有“开锁闭锁”的步骤,同时只单线程的执行操作,执行效率也会降低; | ||
StringBuilder | 效率最快,方法没有使用synchronized关键字修饰,没有“开锁闭锁”步骤,也可以多线程操作; |
( 哈哈哈~~ 文章结束!)
( 看到这里,如果有为各位帅哥美女提供一点点灵感,请点一个小小的赞哦,比心💖💖💖 )