「JavaSE」String类2:StringBuilder和StringBuffer

个人主页:Ice_Sugar_7
所属专栏:快来卷Java啦
欢迎点赞收藏加关注哦!

String类2

  • String的不可变性
  • 修改字符串
  • StringBuilder和StringBuffer
  • 总结

String的不可变性

String类在设计时就规定字符串中的内容不可改变,这点我们可以从源码中看出来:
「JavaSE」String类2:StringBuilder和StringBuffer_第1张图片
要修改字符串,我们就得取到字符数组中的元素,而它用private修饰,并且String类也没提供get方法,所以根本拿不到,也就没法修改咯

注意:
不可修改和被final修饰无关,因为被final修饰的数组仍然可以修改其中的元素,只不过是不能修改value本身的值,即不能引用其它字符数组

由此我们可以作一个总结:

final修饰类表明该类不能被继承
final修饰引用类型表明该引用变量不能引用其他对象,但是其引用对象中的内容是可以修改的

    public static void main(String[] args) {
        final int a = 0;
        a = 10;  //报错,此时a为常量,不可修改
        final String[] array = {"hello","world"};
        array[1] = "China";
        for (String str:array) {
            System.out.println(str);
        }
    }

「JavaSE」String类2:StringBuilder和StringBuffer_第2张图片


修改字符串

因为字符数组value的内容不能被修改,所以:所有涉及到可能修改字符串内容的操作,都是先创建一个新对象,改变的是新对象
所以要修改字符串的话不要采用下面的写法,因为会产生临时对象,导致效率低下

public static void main(String[] args) {
    String str = "hello";
    str += "abc";
    System.out.println(str); // 输出:hello world
}

为什么会产生临时对象呢?我们可以看下汇编代码:

「JavaSE」String类2:StringBuilder和StringBuffer_第3张图片

里面有几行都出现了StringBuilder,而且调用它的构造方法和append方法,说明创建了一个StringBuilder类的对象
上面的汇编代码你可能看不懂,它等价于下面的代码:

public static void main(String[] args) {
    String str = "hello";
    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.append(str);
    stringBuilder.append("abc");
    str = stringBuilder.toString();
    System.out.println(str);
}

这个过程就是:首先创建StringBuilder类的对象,然后向这个对象添加str和"abc",再调用toString得到新字符串(helloabc),赋给str,让str指向helloabc
(StringBuilder对象调用toString()时,它会返回一个表示StringBuilder对象当前内容的字符串)
因为这个过程实例化了对象,所以会有时间和内存上的消耗,每和一个字符串相加就会创建一个对象,加的次数越多,消耗就越大

所以尽量不要直接修改String,如果要修改建议使用StringBuffer或者StringBuilder


StringBuilder和StringBuffer

为了方便字符串的修改,Java提供了StringBuilder和StringBuffer类,这两个类大部分功能是相同的

StringBuilder的append方法返回的this引用,也就是说不管调用多少次append,它都是在原字符串的基础上进行修改,不用new额外的对象

所以,如果遇到需要频繁修改字符串的情况,那就考虑用StringBuilder或StringBuffer吧

「JavaSE」String类2:StringBuilder和StringBuffer_第4张图片
其他涉及到字符串修改的方法也是返回this指针,比如deleteCharAt
「JavaSE」String类2:StringBuilder和StringBuffer_第5张图片
接下来说说StringBuilder和StringBuffer的区别
以append方法为例
「JavaSE」String类2:StringBuilder和StringBuffer_第6张图片
我们发现,相比于StringBuilder,StringBuffer的append方法多了一个关键字synchronized

  • synchronized是用于实现线程同步的,表示在任意时刻只能有一个线程访问该方法或代码块的内容,其他线程必须等待当前线程执行完毕后才能访问。这样可以避免多个线程同时访问共享资源时出现的数据竞争和并发访问的问题
    这就像上厕所,一次只能进一个人,只有当这个人出来之后,其他人才能进去

StringBuffer采用同步处理,属于线程安全操作;而StringBuilder未采用同步处理,属于线程不安全操作。
因此在单线程环境下,StringBuilder的性能会比StringBuffer更好;
但是在多线程环境下,如果有多个线程同时访问一个StringBuilder对象,可能会出现竞态条件,导致数据错误。


总结

String、StringBuffer、StringBuilder的区别:

  1. String的内容不可修改,而StringBuffer和StringBuilder可以修改
  2. StringBuffer与StringBuilder大部分功能是相似的
  3. StringBuffer采用同步处理,属于线程安全操作;而StringBuilder未采用同步处理,属于线程不安全操作

你可能感兴趣的:(快来卷Java啦,java,开发语言)