在Java学习中,String、StringBuffer、StringBuilder三者是很重要的,在编写代码中经常使用到他们,那么深入的了解他们的异同是非常重要的,接下里我们详细剖析下这三个的异同之处
首先总结下这三者的区别:
1.基本区别
String的对象不可变,StringBuffer和StringBuilder的对象是可变的
2.性能区别
三者中StringBuilder执行速度最佳,StringBuffer次之,String的执行速度最慢(String为字符串常量,而StringBuilder和StringBuffer均为字符串变量,String对象一旦创建后该对象是不可更改的,后两者的对象是变量是可以更改的)
3.安全区别
String、StringBuffer是线程安全的,StringBuilder是线程不安全的(所以如果程序是单线程的使用StringBuilder效率高,如果是多线程使用StringBuffer或者String)
其次总结下这三者的相同:
1.三者在java中都是用来处理字符串的
2.三个类都被final修饰,因此都是不可继承的
3.StringBuilder与StringBuffer有公共父类AbstractStringBuilder(抽象类)
接下来我们从源码和案例深入分析这三者:
1.String
String常用方法:
1.length() 获取字符串长度
2.replace() 替换字符串中某些字符
3.equals() 比较两个字符对象内容是否相同
4.substring() 截取一个新的字符串,它是此字符串中的子串
5.trim() 将字符串开头的空白(空格)和尾部的空白去掉
6.indexOf() 求某个字符在字符串中的位置
7.charAt() 求一个字符串中某个位置的值
8.toLowerCase() 将字符串中所有的大写改变成小写
9.toUpperCase() 将字符串中所有的小写改变为大写
注意:
1.String是final类型,不可被继承;
2.String的对象不可变
从上面这个案例我们发现a对象的内容被改变了,不是说不能改变么,这里我们不能被表面迷惑,我们再看下面的程序
我们发现字符串a被重新赋值后其实已经不是它自己了,从hashCode值可以看出。当a字符串创建赋值maxbill,然后重新赋值时又会创建一个a对象值为:maxbill1993,此时844527467是一已经在等待GC回收了,我们看到的实际上是-1438782163对象。所以我们在程序中对字符串使用+连接时,并不是把内容动态的改变进去,而是每次都会创建一个新的String对象去放新的字符内容,原来的对象会等着GC回收,所以这也是String为啥相比其他两者执行慢的原因了。
2. StringBuffer
从StringBuffer类的源码可以看出,其方法都被同步锁synchronized修饰,因此是线程安全的,因此在多线程编程中操作字符串是推荐使用为什么说StringBuffer比String的执行速度要高,前面说了String的原理,是导致其慢的原因,StringBuffer相比快是因为使用了字符串变量,是可以动态改变的,不必像String一样总是去创建对象赋值新内容,我们
看下面的案例就明白了
由上面的案例可以看出StringBuffer在修改字符串内容时,不会创建新的对象,因此它比String类效率更高
StringBuffer常用方法:
1.length() 获取StringBuffer字符长度
2.append() 向StringBuffer增加字符
3.delete() 删除StringBuffer中的字符
4.replace() 替换StringBuffer中的字符
5.insert() 向StringBuffer中插入字符
6.toString () 把StringBuffer转成字符串
StringBuffer的append方法源码解读:
调用了父类的append方法,我们看下父类append的源码
基本原理:使用append()方法在字符串后面追加东西的时候,如果长度超过了该字符串存储空间大小了就需要进行扩容,构建新的存储空间更大的字符串,将旧的数据的复制过去
详细原理:char value[]用来存储数据,int count用来记录字符长度,StringBuffer初始16个字符容量 ,先记录下传进来字符串的长度,然后使用ensureCapacityInternal函数判是否需要扩容,如果容量不够则使用newCapacity进行扩容,新容量扩为原来2倍+2,存储容量够了使用getChars函数复制数据,最后将count更新。
3. StringBuilder
StringBuilder和StringBuffer的使用方法和原理基本一致的,唯一的区别就是StringBuilder是线程不安全的,执行效率要比StringBuffer高,因此当时单线程的时候推荐使用线程不安全的StringBuilder效率更高一些,如果是多线程推荐使用StringBuffer来保证线程安全