String,StringBuffer,StringBuilder

字符修改

String是不可变字符序列(修改String类时,会新增String对象);StringBuffer和StringBuilder进行修改时不会产生新的对象

UML图解

线程安全

String由于不可变,所以是线程安全;
String和StringBuffer类中每个方法都用synchronized修饰所以是线程安全的;
StringBuilder并不是线程安全的

解释: String不可变,无论是多线程还是单线程都是安全的;StringBuffer每个方法都加了synchronized,无论多线程还是单线程都是安全的;StringBuilder是可变字符序列,没有加上同步锁;是线程不安全的

执行效率

String由于每次修改都会创建新的对象,所以在操作大量数据时效率最慢
StringBuffer由于每个方法都加了synchronized修饰,所以每次执行都需要等待锁释放,效率居中
StringBuilder效率最快

String

String 使用一个final修饰的char数组value维护,value被final修饰不可改变,这也就是String为什么是不可变字符序列

String 真的不可变吗?

由上可知,String的成员变量都是用private final修饰的,初始化后不可以改变。但是value比较特殊,它是一个引用变量,并不是真正的对象。value是final修饰的,也就是说value不能再指向其他数组对象,但我们可以改变value指向的数组中的值。
使用普通的代码无法做到,因为我们不能访问到value的引用,更不能通过引用去修改数组。我们可以使用反射访问私有成员,进而改变value所指向数组的结构

public static void main(String[] args) throws Exception {

        //创建字符串"Hello World", 并赋给引用s
        String s = "Hello World";

        System.out.println("s = " + s); //Hello World
        System.out.println("修改前的str的内存地址" + System.identityHashCode(s));

        //获取String类中的value字段
        Field valueFieldOfString = String.class.getDeclaredField("value");

        //改变value属性的访问权限
        valueFieldOfString.setAccessible(true);

        //获取s对象上的value属性的值
        char[] value = (char[]) valueFieldOfString.get(s);

        //改变value所引用的数组中的第5个字符
        value[5] = '_';

        System.out.println("s = " + s);  //Hello_World
        System.out.println("修改前的str的内存地址" + System.identityHashCode(s));

    }

StringBuffer和StringBuilder

StringBuffer和StringBuilder都继承了AbstractStringBuilder,他们存储字符的字符数组来自父类的value,这个value并不是final类,可以被修改;对StringBuffer和StringBuilder进行修改可以使用append的方法,在原有的字符序列后面加上新增的字符值(父类AbstractStringBuilder中的方法可以看出这样的操作);所以也就解释了为什么StringBuffer和StringBuilder为什么是可变字符序列

StringBuilder append(String str) 方法源码分析

StringBuilder

AbstractStringBuilder

原文地址:https://www.cnblogs.com/conglingkaishi/p/15127484.html