String类
String类代表字符串,Java 程序中所有字符串字面值(“abc” )都作为此类的实例实现。
String类的特点
- 字符串是常量;它们的值在创建之后不能更改。即一旦这个字符串确定了,就会在字符串的常量池中生成这个字符串。
//演示字符串是常量
String str = "pq";
str = "abc";
当这两句话执行完之后,在字符串常量池中有两个字符串,str引用先指向"pq"这个字符串,然后紧接着str引用"abc"。那么"pq"就没有引用在指向它了。
- String 对象是不可变的,可以共享。原因在于字符串一旦生成,在常量池中是不可变的,那么不管有多少个引用,只要他们的引用的字符串相同,这些引用指向的内存区域相同。
//演示字符串可以共享
String str1 = "itcast";
String str2 = "itcast";
System.out.println(str1==str2);
输出的结果为true,就说明str1的引用和str2的引用指向的同一片内存区域。
- 字符串有大量重载的构造函数。通过String类的构造函数可以知道,将字节数组
或者字符转成字符串。
String s3 = "abc";
String s4 = new String("abc");
System.out.println(s3==s4);//false, 因为String复写了equals方法,建立字符串自己的判断相同的依据。通过字符串对象中的内容来判断的。
System.out.println(s3.equals(s4));//true,
上述代码中s3和s4有什么不同呢?
s3创建,在内存中只有一个对象。这个对象在字符串常量池中。
s4创建,在内存中有两个对象。一个new的对象在堆中,一个字符串本身对象,在字符串常量池中。
StringBuffer类
查阅StringBuffer的API,线程安全的可变字符序列。一个类似于 String 的字符串缓冲区,但不能修改。虽然在任意时间点上它都包含某种特定的字符序列,但通过某些方法调用可以改变该序列的长度和内容。
- 是一个字符串缓冲区,其实就是一个容器。
- 长度是可变,任意类型都行。注意:是将任意数据都转成字符串进行存储。
- 容器对象提供很多对容器中数据的操作功能,比如:添加,删除,查找,修改。
- 所有的数据最终变成一个字符串
StringBuilder
查阅StringBuilder的API,是一个可变的字符序列。此类提供一个与 StringBuffer 兼容的 API,但不保证同步。该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。如果可能,建议优先采用该类,因为在大多数实现中,它比 StringBuffer 要快。
StringBuilder继承自AbstractStringBuilder实现了CharSequence和Serializable:
- AbstractStringBuilder实现了Appendable(可扩展的)接口,要实现的方法append()
- AbstractStringBuilder实现了CharSequence字符序列接口(同数据结构中List的定义)
StringBuilder的构造函数是创建一个默认容量为16的字符数组,随着后续内容的增加,底层再进行动态的扩容。简单来说,StringBuilder就是一个可变长可修改内容的String.
StringBuffer和StringBuilder区别
从API中可以发现,StringBuffer和StringBuilder基本完全一样。它们之间最大的区别在于线程是否安全:
- StringBuffer是线程安全的——多线程环境下和单线程环境下不容易出错
- StringBuilder是线程不安全——多线程环境下容易出错单线程环境下不容易出错
- 在单线程情况下,StringBuilder比StringBuffer效率高一些,因为不需要判断锁这个问题
- 在多线程情况下StringBuffer比StringBuilder安全高一些,因为需要判断锁这个问题
从代码的角度而言,StringBuffer里面的大部分成员函数都有synchronized关键字修饰