在java中存储字符串的时候,最先考虑到的就是String,StringBuffer和StringBuilder,那么这三个的区别有什么异同呢?我们先看一下源码。
/** The value is used for character storage. */
private final char value[];
通过上面String类的源码可以看到,该类通过final关键字修饰字符数组保存字符串,所以我们修改String并不会在原来内容上进行更改,而是重新创建一个新的对象并把引用替换掉原先对象的引用。
例如:String a="你好"; a="hello";
上面代码首先创建一个"你好"的对象,并且把引用赋给a;当执行a="hello"的时候,会创建一个"hello"对象,并且把"hello"对象的引用赋给a,最终a保存的是"hello"对象的引用。
注:创建对象之前如果字符串常量池有对应的值,就不会创建新对象,而是直接返回常量池中对应的引用;如果不在池中,就会实例化一个字符串并放入池中。
接下来进入StringBuffer,StringBuilder类,会发现这两个类都继承AbstractStringBuilder类,我们可以看到,他们也是通过字符数组保存字符串,但没有使用final关键字修饰,那也就意味着StringBuffer,StringBuilder这两个类可以在原数据上进行修改。
/** The value is used for character storage. */
char[] value;
当我们进行操作时之后。
String a="a";
System.out.println(a);
System.out.println(a.hashCode());
a=a+"c";
System.out.println(a);
System.out.println(a.hashCode());
System.out.println("=======================================");
StringBuffer stringBuffer=new StringBuffer("aa");
System.out.println(stringBuffer);
System.out.println(stringBuffer.hashCode());
stringBuffer.append("cc");
System.out.println(stringBuffer);
System.out.println(stringBuffer.hashCode());
结果为:
a
97
ac
3106
=======================================
aa
460141958
aacc
460141958
在查看StringBuffer,StringBuilder类代码的时候,我发现StringBuffer类中用到了大量的synchronized关键字修饰方法,这也就意味着StringBuffer是线程安全的,而StringBuilder则没有。因为String是使用final关键字修饰,被final修饰将不可被修改,也属于线程安全。
synchronized关键字解决了多个线程之间访问资源的同步性;
synchronized关键字用于修饰方法和代码块;
synchronized关键字声明的数据具有可见性和原子性;
既然StringBuffer属于线程安全,那么StringBuilder性能会比StringBuffer高;而在String中,因为有可能涉及到新建对象操作,所以性能会比前面两者低。
操作方法:String操作引用;StringBuffer,StringBuilder操作原内容
线程安全:StringBuffer = String > StringBuilder
性能:StringBuilder > StringBuffer > String
以上内容可能存在不足或错误,如有发现请指出来。