1、首先是String和后两者的区别,这三者都是字符串操作,但是String中的value[]有一个final进行修饰,相当于其是不可变的,如果我们想要更改它的值那就是要在堆内存中再开辟出一个空间用来存储这个新的值,而原来的值还占着内存,这样就会造成大量的内存被占用,这个方面通过new String();创建字符串对象也会造成大量的内存被占用,而StringBuilder和StringBuffer都是继承了AbstractStringBuilder这个虚拟的类,里边的value[]没有用final进行修饰所以其值是可变的,这样对内存就比较友好。

2、然后我们再来说说StringBuffer和StringBuilder的区别,这两个主要的区别就是安全问题和效率问题,StringBuilder效率比较高但是线程不安全,StringBuffer效率低但是线程安全,至于会造成这个问题的原因我们现在就来研究一下。

先举一个例子,我们要初始化2000个线程来用append()方法向这两个对象中添加2000个字符“a”,首先是StringBuilder对象

![在这里插入图片描述]()

但是经过测试,我们最后输出StringBuilder的长度却是1991如果我们多次执行,最后的结果数值也是不同的,为什么会造成这种结果呢?,我们从他的源码来看看

![在这里插入图片描述]()

在这里边都是继承了父类的方法,对字符串进行了添加,并且如果字符数组的长度不够对它进行扩容操作,然后通过getChars()方法对其进行了添加,这里有一个 `count+=len;`操作,并且这个append方法没有规定同时只能由一个线程访问,假设原来的字符串长度是100,接下来如果有两个线程同时访问了这个方法对其进行了添加然后第三个线程进来访问这个长度是多少呢?是101,没错,不是102,因为同时两个线程对其进行了访问所以导致其长度发生了变化,与真实的数据不符合这也就导致了我们上边的每次输出的长度都不一样的问题。

接下来再看StringBuffer

java中stringbuilder用法 java string stringbuilder_java


这里的结果就是正确的然后我们来看他的append方法

java中stringbuilder用法 java string stringbuilder_字符串_02


它在前边加了一个synchronized来修饰,相当于同时只能有一个线程来访问他,这样就不会产生上边的问题但同时他的效率也就比StringBuilder低,