一、字符串的不可变性
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);//hellostr += "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**///Stringlong 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));//StringBufferstart = 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));//StringBuilderstart = 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修饰,都保证了线程安全。