String : 1.String是被final修饰的类,不能被继承。
2.String底层是通过char类型的数据实现的,并且被final修饰,所以字符串的值创建之后 就不可以被修改,也就是说字符串具有不可变性。
String s = "明天会下雨";
s.concat("吗");//连接字符串
System.out.println(s);//结果:明天会下雨
String str = "X";
str = str.concat("A");//连接字符串,产生新的字符串
str = str.concat("B");//连接字符串,产生新的字符串
System.out.println(str);//结果: XAB
String str = "天王盖地虎";
str.replace('天', '地');//替换字符
str.replace("虎", "湖");//替换字符串
System.out.println(str);//字符串仍为原字符串
通过以上代码也可以看出来字符串具有不可变性。无论是连接或者修改(字符)字符串亦或者其他的操作,不会在原来的内存地址进行修改。而是重新分配新的内存地址进行赋值,产生新的字符串。
StringBuffer、StringBuilder和String类似,底层也是用一个数组来存储字符串的值,并且数组的默认长度为16,即一个空的StringBuffer对象数组长度为16。实例化一个StringBuffer对象即创建了一个大小为16个字符的字符串缓冲区。但是当我们调用有参构造函数创建一个StringBuffer对象时,数组长度就不再是16了,而是根据当前对象的值来决定数组的长度,数组的长度为“当前对象的值的长+16”。所以一个 StringBuffer 完成创建成之后,有16个字符的空间可以对其值进行修改。如果修改的值范围超出了16个字符,会先检查StringBuffer对象的原char数组的容量能不能装下新的字符串,如果装不下则会对 char 数组进行扩容。
//内部字符数组的长度默认为16
StringBuilder sb1 = new StringBuilder();
System.out.println(sb1);
//内部字符数组的长度: str.lenght() + 16
StringBuilder sb2 = new StringBuilder("abc");
System.out.println(sb2);
String 、(StringBuilder 、 StringBuffer的相同点与不同点)的区别:
相同点:底层都是通过char数组实现的
不同点:
1.String对象一旦创建,其值是不能修改的,如果要修改,会重新开辟内存空间来 存储修改之后的对象;而StringBuffer和StringBuilder对象的值是可以被修改的。
2.StringBuffer几乎所有的方法都使用synchronized实现了同步,线程比较安全, 在多线程系统中可以保证数据同步,但是效率比较低;而StringBuilder 没有实现 同步,线程不安全,在多线程系统中不能使用 StringBuilder,但是效率比较高。
3.如果我们在实际开发过程中需要对字符串进行频繁的修改,不要使用String,否 则会造成内存空间的浪费;当需要考虑线程安全的场景下使用 StringBuffer,如 果不需要考虑线程安全,追求效率的场景下可以使用 StringBuilder。
//String 是不可变字符串
// 相同点: 都是可变字符串,都是AbstractStringBuilder类的子类
// 不同点:
// StringBuilder类中的方法没有使用synchronized关键字,所以它的方法都是“线程”不安全,但是性
能好
StringBuilder strBuilder = new StringBuilder();
strBuilder.append("");
// StringBuffer类中的方法使用synchronized关键字,所以它的方法都是“线程”安全,但是性能差
StringBuffer strBuff = new StringBuffer();
strBuff.append("");