zoukankan      html  css  js  c++  java
  • 深刻理解Java中的String、StringBuffer和StringBuilder的差别

          声明:本博客为原创博客,未经同意。不得转载!小伙伴们假设是在别的地方看到的话,建议还是来csdn上看吧(链接为http://blog.csdn.net/bettarwang/article/details/26412497),看代码和提问、讨论都更方便。

    首先简单地来梳理一下Java中String、StringBuffer和StringBuilder各自的含义。

    1.String类

        首先。它是线程安全的,即能够用于多线程编程中。

        其次,String类的对象是不可变的,即在定义时就确定了,类似String str="Hello";str+="Java";的语句事实上是生成了新的对象,仅仅是我们未察觉到而已。可是注意在大量的字符串新建对象时消耗就非常可观。这时必须考虑採用StringBuffer或StringBuilder,否则会极大地减少程序的效率。

    2.StringBuffer类:

          首先,它也是线程安全的。

          其次,它是可变类,对它指向的字符串的操作都不会产生新的对象。 每一个StringBuffer对象都有一定的缓冲区容量,当字符串大小没有超过容量时,不会分配新的容量,当字符串大小超过容量时,会自己主动添加容量。因而它的效率要比String高。 

           StringBuffer 类最经常使用的两个方法是 append 和 insert 方法,StringBuffer已经重载了这些方法,以接受随意类型的数据,所以小伙伴们。如果strBuffer是StringBuffer的对象。那么像strBuffer.append(3.14f);strBuffer.append(true);这种语句都是全然合法的

     3.StringBuilder类:

            首先,它不是线程安全的。即仅仅能用于单线程编程中。

             其次。它跟StringBuffer类似,即其对象也是一个可变的字符序列。可是要注意的是它以下几种构造方法:

             StringBuilder():创建一个容量为16的StringBuilder对象。

             StringBuilder(int capacity):创建一个容量为capacity的StringBuilder对象;

             StringBuilder(String s):创建一个包括s的StringBuilder对象。同一时候末尾加入16个空元素。

             StringBuilder(CharSequence cs):创建一个包括cs的StringBuilder对象,末尾附加16个空元素;  

          综上可知。在线程同步方面。String和StringBuffer是线程安全的,而StringBuilder不是线程安全的;在运行效率上,StringBuilder>StringBuffer>String,因而在须要大量的进行字符串操作的单线程场合,应该昼使用StringBuilder以提高效率,在大量进行字符串操作的多线程情形,StringBuffer无疑是最佳的选择。而对于少量的字符串操作的单线程或多线程情形下,使用String则更为简单、方便。

         上面对这三个类进行了一下梳理,但这仅仅是基础知识,根本谈不上深刻理解。取这么一个题目不是想哗众取宠。以下就開始结合我自己的一些经历谈一下自己的理解。

         我们都知道,String类的对象是不可变的。可是又考虑到Java中”一切皆引用“,以为在函数中传String引用能够实现值的改变。因而经常犯以下这种错误:

    import java.util.*;
    import java.io.*;
    
    public class StringTest
    {
       private static void treatString(String str)
       {
         if(str.contains("hello"))
         {
           str="hello java";
         }
         else
         {
           str="enjoy java";
         }
       }
    
       public static void main(String[]args)
       {
          String str1="hello world";
          String str2="study java";
          treatString(str1);
          treatString(str2);
          
          System.out.println(str1);
          System.out.println(str2);
       }
    }
       
          

    输出结果例如以下图所看到的:


          本来期望传递引用从而改变字符串str1和str2的值,可是从输出结果看字符串的值却是根本没有被改变,这是为什么呢?

         原来确实传递的也是引用。可是与一般的对象不同,treatString(String)函数并没有对str指向的对象进行改动(或者说并没有在str指向的内存地址上进行改动)。而是新建了一个String对象。可是这个新建的对象却是仅仅有形參指向它,实參并没有指向它。实际上整个过程中实參str都始终还是指向最開始那个对象。所以不难理解为什么会有这种输出结果。

        那么假设想要获得一般对象传递引用的效果该怎么办?

        非常easy,第一种方法,也是我个人比較推荐的方法,就是返回值String而不是void,即将上面的代码改动为:

    import java.util.*;
    import java.io.*;
    
    public class StringTest
    {
       //private static void treatString(String str)
        private static String treatString(String str)
       {
         if(str.contains("hello"))
         {
           str="hello java";
         }
         else
         {
           str="enjoy java";
         }
         
         return str;
       }
    
       public static void main(String[]args)
       {
          String str1="hello world";
          String str2="study java";
          str1=treatString(str1);
          str2=treatString(str2);
          
          System.out.println(str1);
          System.out.println(str2);
       }
    }
       
          
    此时输出结果例如以下图所看到的:



    显然。此时已经达到了我们预期的目的。

         到了这里,我再结合自己的还有一个经历,就是一開始对String.replace(oldChar,newChar);这个函数不熟悉。以为仅仅要调用它就能够实现str的改变(即以为直接str.replace(oldChar,newChar);就能实现str的改变),实际上要利用它的返回值才干改变str,即str=str.replace(oldChar,newChar);才是正确的做法。

          另外一种方法,当然就是利用StringBuffer和StringBuilder喽,由于它们是对象可变的嘛。

    详细样例到后面再追加。今天先写到这里吧。

    晚安啦,小伙伴们!  

  • 相关阅读:
    171. Excel Sheet Column Number (Easy)
    349. Intersection of Two Arrays (Easy)
    453. Minimum Moves to Equal Array Elements (Easy)
    657. Judge Route Circle (Easy)
    CSS笔记
    保存页面状态
    UI开发总结
    ubuntu 下配置munin
    反向代理配置
    JavaScript 高级程序设计第二版
  • 原文地址:https://www.cnblogs.com/slgkaifa/p/6977857.html
Copyright © 2011-2022 走看看