String,StringBuffer,StringBuilder的区别
一、相同点
1.都是final类,不允许被继承。之所以使用final,是因为这几个类使用频率很高,防止其中方法被重写。
二、不同点
1.运行速度:StringBuilder > StringBuffer > String。
2.线程安全:StringBuffer 是线程安全的,StringBuilder是线程不安全的。
三、深层次解析
1.为啥String速度最慢?
这里说的速度慢,是指在执行修改操作时,三者的速度比较。String是字符串常量,不可变的。例如以下代码:
public static void main(String[] args) { String str="hello"; str= str + "123"; //创建一个str引用的拷贝,然后创建一个新对象“hello123”,引用指向新对象。 System.out.println(str); //原来的str在引用指向新对象的时候,就会被gc回收掉 }
StringBuffer与StringBuilder则是字符串变量,可变的,没有进行对象的创建与销毁,所以速度略快。而StringBuilder 的速度之所以大于StringBuffer,是因为StringBuffer是线程安全的,它的操作都是被synchronized修饰,所以在性能上有所下降。例如源码:
StringBuffer类
@Override public synchronized StringBuffer append(String str) { toStringCache = null; super.append(str); return this; }
StringBuilder类
public StringBuilder(String str) {
super(str.length() + 16);
append(str);
}
2.重载+ 与StringBuilder
我们看下面两段代码:第一段编译器首先会自动优化程序,将自动引入StringBuilder来执行,但是由于每个循环中都要 new StringBuilder(),还要销毁对象,所以耗时很长,达到270ms。第二段代码则直接使用StringBuilder,不存在反复的创建与销毁对象,所以运行速度很快。所以在拼接长字符串时,不考虑线程安全的情况,使用StringBuilder最好。
public static void main(String[] args) { long stime = System.currentTimeMillis(); String s="hello"; for(int i = 0;i<10000;i++){ s = s + i; } long etime = System.currentTimeMillis(); System.out.println(s); System.out.println(etime-stime); }
结果耗时大约:273ms
public static void main(String[] args) { long stime = System.currentTimeMillis(); StringBuilder s= new StringBuilder(); s.append("hello"); for(int i = 0;i<10000;i++){ s.append(i); } long etime = System.currentTimeMillis(); System.out.println(s.toString()); System.out.println(etime-stime); }
结果耗时大约:2ms