一、字符串的不可变性
1.String本身不可变
字符串修改注意:尽量避免直接对 String 类型对象进行修改,因为 String 类是不能修改的,所有的修改都会创建新对象,效率 非常低下。
public static void main(String[] args) {
/**
* String 本身是不可修改的
* 下面代码,创建了三个对象 "hello" "abc" "helloabc"
* 查看源码 private final char value[];
* 发现 如果想要改变str 那么就需要拿到 value[]这个值,但是这个值被 private 所修饰
* 所以在 String类 外部,无法拿到或者修改这个 value值
*/
String str = "hello";
System.out.println(str);//hello
str += "abc";
System.out.println(str);//helloabc
/**
* 但是从运行结果上来看,好像的确 变成了 helloabc
* 打开cmd 查看 java汇编码
*/
}
String 类中的字符实际保存在内部维护的 value 字符数组中 ,该图还可以看出:1. String类被final修饰,表明该类不能被继承
2. value被修饰被final修饰,表明value自身的值不能改变,即不能引用其它字符数组,但是其引用空间中 的内容可以修改。
3.value被修饰被privatel修饰,如果想要改变str 那么就需要拿到 value这个值,但是这个值被 private 所修饰 所以在 String类 外部,无法拿到或者修改这个 value值。
2.Stringbuilder
根据汇编码,发现String在拼接字符串的时候创建了StringBuilder这个对象
用StringBuilder模拟实现
发现能实现同样的效果 helloabc
public static void main2(String[] args) {
/**
* StringBuilder
* 根据上面main1代码的汇编代码,模拟以下代码
*/
String str = "hello";
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(str);
stringBuilder.append("abc");
str = stringBuilder.toString();
System.out.println(str);//helloabc
}
二、比较String 、StringBuffer、StringBuilder
public static void main(String[] args) {
/**
* 对比String 、StringBuffer、StringBuilder
*
*/
//String
long start = System.currentTimeMillis();//执行开始时间
String string = "";
for(int i = 0; i < 10000; ++i){
string += i; //在空字符串后,循环拼接10000次字符
}
long end = System.currentTimeMillis();//执行结束时间
System.out.println("String前后执行的时间:"+(end - start));
//StringBuffer
start = System.currentTimeMillis();
StringBuffer stringBuffer = new StringBuffer("");
for(int i = 0; i < 10000; ++i){
stringBuffer.append(i);
}
end = System.currentTimeMillis();
System.out.println("stringBuffer前后执行的时间:"+(end - start));
//StringBuilder
start = System.currentTimeMillis();
StringBuilder stringBuilder = new StringBuilder();
for(int i = 0; i < 10000; ++i){
stringBuilder.append(i);
}
end = System.currentTimeMillis();
System.out.println("stringBuilder前后执行的时间:"+(end - start));
}
发现
String拼接字符串时,耗费的时间最长。
StringBuffer和StringBuilder 两者耗费时间相差不大,都是极短的。
String 与 StringBuffer、StringBuilder最大的区别就在于 StringBuffer、StringBuilder调用了append函数。
查看append 底层代码逻辑
返回的是this
查看汇编比较
1.String 在循环拼接字符串内时,每一次循环都 new了一个StringBuilder对象
2.StringBuffer 每次循环不会new新的对象,直接返回 stringBuffer 的值
3.StringBuilder 也没有在每次循环中创建新的对象
1)对比String 和 StringBuffer、StringBuilder
String 不可变, StringBuffer、StringBuilder可变
String每次循环都在创建对象、 拼接对象、 销毁对象,无形之中消耗了大量时间
而StringBuffer、StringBuilder 直接在该字符串的位置后拼接对象,返回的这个字符串的地址
耗费时间自然就少了许多
2)对比StringBuffer 和 StringBuilder
StringBuffer 的append方法 被synchronized所修饰了,这个保证了线程安全,而StringBuilder 没有线程安全
StringBuffer 里所有的方法都被synchronized修饰,都保证了线程安全。