String、StringBuffer、StringBuilder的区别

h3>首先,从性能、速度方面来说:

StringBuilder > StringBuffer > String

我们来做一个测试,我们分别使用String和StringBuilder创建变量,然后分别对它们进行加字符串操作,由于时间太短,我们把这个过程使用for循环重复100000遍以放大差距:

``` public static void main(String[] args) {
    Long start1 = System.currentTimeMillis();//获取开始时间
    for (int i=0;i<100000;i++)//重复10万次进行String变量加操作
    {
        String str = "a";
        str+="b";
    }
    Long end1 = System.currentTimeMillis();//获取结束时间
    System.out.println("String花费时间:"+(end1-start1));//打印出花费的时间

    Long start2 = System.currentTimeMillis();
    for (int i=0;i<100000;i++)//重复10万次进行StringBuilder变量加操作
    {
        StringBuilder str2 = new StringBuilder("a");
        str2.append("b");
    }
    Long end2 = System.currentTimeMillis();
    System.out.println("StringBuilder花费时间:"+(end2-start2));

    Long start3 = System.currentTimeMillis();
    for (int i=0;i<100000;i++)//重复10万次进行StringBuffer变量加操作
    {
        StringBuffer str2 = new StringBuffer("a");
        str2.append("b");
    }
    Long end3 = System.currentTimeMillis();
    System.out.println("StringBuffer花费时间:"+(end2-start2));
}
<p>实验结果:<br>
<img src="https://img-blog.csdnimg.cn/20181222205044650.png" alt="在这里插入图片描述"><br>
可以看到,放大了差距之后,String和StringBuilder、StringBuffer两兄弟的差距还是蛮大的,那么是什么造成了这种差距呢?</p>
<p>在上面的程序中:</p>
<pre><code>String str = "a";
str+="b";
</code></pre>
<p>这句话看似是对同一个String类型的str对象进行了加操作,但是实际上可不是同一个对象,事实上,我们先声明了一个String类型的对象,值是"a",把str这个句柄指向了这个对象,然后,当我们把这个对象进行+=操作的时候,实际上是又创建了一个String对象,这个对象的值是"a"+“b"也就是"ab”,然后改变句柄str让它指向了这个新的对象,原来的对象失去了引用,就被jvm垃圾回收了。而StringBuffer和StringBuilder可不是这样,这两兄弟是直接改变自己本身对象的值。<br>
那么,当我们进行了10万次操作的时候,快慢差距自然就体现出来了。</p>
<p>这里有人会问了,如果我把这句代码:</p>
<pre><code>String str = "a";
str+="b";
</code></pre>
<p>改为:</p>
<pre><code>String str = "a"+"b";
</code></pre>
<p>呢?</p>
<p>让我们看一下执行效果:<br>
<img src="https://img-blog.csdnimg.cn/20181222210226399.png" alt="在这里插入图片描述"><br>
哪怕是进行10万次操作,String所花费的时间也是极少的,这是为什么呢?</p>
<p>这是因为String和我们其它类型的变量不同,其它的非基本类型对象的值、数据都存储在java的堆中,而String类型的变量的值是存储jvm在方法区中的字符串常量池中的。当我们执行:String str = “a”+“b”;这句话的时候,String会自动把这个对象的值看成"ab",然后在方法区中如果找到了值同样为"ab"的,就会直接让str句柄指向它,也就是说,我们的这句代码现在相当于:</p>
<pre><code>String str = "ab";
</code></pre>
<p>这可比之前的String用法一遍遍反复地去创建对象回收对象快多了,因此,即使重复10万次依然还是很快。</p>
<h3><a id="_208"></a>从线程安全的角度去看</h3>
<p>StringBuffer是线程安全的,而StringBuilder是线程不安全的,实验的具体方法见此链接:<a href="https://blog.csdn.net/litterfrog/article/details/76862435">https://blog.csdn.net/litterfrog/article/details/76862435</a></p>
<h1><a id="_212"></a>总结</h1>
<p>String适用于少量的字符串操作的情况<br>
StringBuilder适用于单线程下在字符缓冲区进行大量操作的情况<br>
StringBuffer适用多线程下在字符缓冲区进行大量操作的情况</p>

<p>转自:<a href="https://blog.csdn.net/qq_37856300/article/details/84340288">https://blog.csdn.net/qq_37856300/article/details/84340288</a></p>
posted @ 2020-02-22 15:10  whjykgz  阅读(125)  评论(0编辑  收藏  举报