相信有很多同学都是经常使用String的,或者也或多或少的听说过StringBuffer,StringBuilder,那么在经常遇见的面试题中(标题),到底这三个的区别是什么呢?让我们来一探究竟!

String
可能看过String源码的同学都知道String这个类是被final继承的类,也就是说我们创建的String对象其实是一个常量,无法修改的数据,当我们对这个string进行操作的时候,其实是创建了一个新的String对象,之前的String对象就没有了引用.
下面我们来看一下String类的定义:

public final class String

那么我们在创建String对象的时候并变更的时候,其实是创建了一个新的String对象.我们用代码来演示一下:

    String s1 = "卢本伟";
        System.out.println(s1);
        s1 = "没开挂";
        System.out.println(s1);

结果:

卢本伟
没开挂

当s1第二次赋值的时候,其实创建了一个新的字符串对象,而本来的"卢本伟"则已经没有了指针去引用它,GG
String的对象如果想要加新的字符的时候可以直接使用加号+ 来操作,但是也一样是创建一个新的字符串,下面演示一下:

String s1 = "卢本伟";
        System.out.println(s1);
        s1 = s1 + "没开挂";
        System.out.println(s1);
        s1 += "!!!!";
        System.out.println(s1);

结果:

卢本伟
卢本伟没开挂
卢本伟没开挂!!!!

这里就不多介绍关于String类的相关方法了,有兴趣的可以研究一下源码或者大佬的文章,我们先来进入主题…

区别
String是被final修饰的,不可变的,大佬们在使用后发现总这样也不行啊,于是诞生了StringBuffer,那么StringBuffer是可以改变的,但是它是一个线程安全的对象,一次只可以改变一个,那么这样效率也不会很快啊,那怎么办呢?后来大佬在1.5的时候又诞生了StringBuilder,线程不安全,但是速度快,我们可以在下面演示一下String,StringBuffer,StringBuilder的速度区别:

//假设我们先设计50万个数据,然后我们使用字符串拼接来测试三者的区别:
public static void main(String[] args) {
        final int T = 500000;
        long startTime = System.currentTimeMillis();
        String str = "*";
        for (int i = 0; i < T; i++) {
            str += "*";
        }
        long endTime = System.currentTimeMillis();
        System.out.println("+=用了:" + (endTime - startTime) + "毫秒");

        startTime = System.currentTimeMillis();
        StringBuffer stringBuffer = new StringBuffer("*");
        for (int i = 0; i < T; i++) {
            stringBuffer.append("*");
        }
        endTime = System.currentTimeMillis();
        System.out.println("StringBuffer用了:" + (endTime - startTime) + "毫秒");

        startTime = System.currentTimeMillis();
        StringBuilder stringBuilder = new StringBuilder("*");
        for (int i = 0; i < T; i++) {
            stringBuilder.append("*");
        }
        endTime = System.currentTimeMillis();
        System.out.println("StringBuilder用了:" + (endTime - startTime) + "毫秒");
    }

结果如下:

+=用了:57958毫秒
StringBuffer用了:7毫秒
StringBuilder用了:4毫秒

可以看出,StringBuffer和StringBuilder的速度接近是普通字符串拼接的一万倍

总结
String是不可变的,创建后为常量,操作之后会新创建一个字符串,数据大的适合不推荐使用,效率较慢
StringBuffer是可变的,速度较快,线程安全,适合在多线程的时候使用,
StringBuilder是可变的,速度最快,线程不安全,适合在单线程的适合使用