JAVA中的String三兄弟

来源:互联网 发布:刺马真相知乎 编辑:程序博客网 时间:2024/04/29 10:15

    在编写Java程序时,我们经常需要对某些字符串进行拼接,之前我们经常用“+”来拼接,但在Java中如果我们直接使用这种拼接方法,会建立很多String型的对象,这样一来,系统就会因为过多的String型对象而对服务器对象和系统性能造成很大的影响。所以,Java中有一种更好的拼接字符串的方法:使用StringBuffer或StringBuilder。

一、String和StringBuffer

◎ String :是不可变类,任何对String的改变都会产生新的String对象。

    当我们使用String来拼接两个字符串时,我们可以执行下面的几行代码:

<span style="font-family:FangSong_GB2312;font-size:18px;">String a ="123";String b = "456";String c = a + b;</span>

 

    这样拼接出来的字符串为:123456。而在程序执行完毕时,我们会发现为了满足程序执行的需要,系统在执行过程建立了a,b,c三个对象。也就是说,使用String的“+”方法来拼接字符串时,会产生很多String类型的新对象,用来满足程序调用和执行的需要。因此,当建立的对象过多,系统的性能和执行效率会因此而受到影响。

◎ StringBuffer:可变类,任何对它所指代的字符串的改变都不会产生新的对象

   使用StringBuffer执行两个字符串相加的操作过程:

<span style="font-family:FangSong_GB2312;font-size:18px;">    StringBuffer sb1 = new StringBuffer(str1);    sb1.append(str2);    String result1 = sb1.toString();</span>

   当这个过程执行完毕,我们所需要的内容只有result1这一个对象,而执行过程中间出现的sb1就已经是垃圾回收的目标了。这样不仅仅避免了执行过程中建立的多个String对象,而且降低了CPU的利用度。

   此时,如果我们要实现sb1,sb2,sb3三个字符串的拼接,我们只需要在刚才的基础上,继续执行便可:

<span style="font-family:FangSong_GB2312;font-size:18px;">StringBuffer sb2 = new StringBuffer(result1);sb2.append(str3);String result2 = sb2.toString();</span>

   这样,对我们有用的就只有result2对象一个,其中生成的sb2和result1都已经成了系统回收的目标。如果继续增大字符串的数量,系统就会相应地产生若干个StringBuffer和String的垃圾对象。

   而Java中的垃圾首先是占用内存的,然后Java的虚拟机会请垃圾回收的线程来回收这些垃圾,这样就又会出现CPU的损耗,同事这些垃圾对象生成的时候也会产生系统开销,所以如果在一个循环中使用字符串的“+”,导致的系统开销将是不可忽略和不可估量的。

   但是相对于StringBuffer来进行字符串连接的话,

<span style="font-family:FangSong_GB2312;font-size:18px;">StringBuffer sb = new StringBuffer();sb.append(str1);sb.append(str2);.....sb.append(strN);String result = sb.toString();</span>

   除去中间的一个StringBuffer对象最后会被抛弃掉,其他的都是有效对象,比起上面产生的一对垃圾,提高的效率不是一星半点。

二、StringBuffer和StringBuilder

◎ StringBuffer

   StringBuffer:字符串变量(Synchronized,即线程安全)。如果要频繁对字符串内容进行修改,出于效率考虑最好使用StringBuffer,如果想转成String类型,可以调用StringBuffer的toString()方法。

   StringBuffer 上的主要操作有append和insert方法。

◎ StringBuilder 

    StringBuilder:字符串变量(非线程安全)。在内部,StringBuilder对象被当作是一个包含字符序列的变长数组。java.lang.StringBuilder是一个可变的字符序列,是JDK5.0新增的。此类提供一个与 StringBuffer 兼容的 API,但不保证同步。该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。

二者比较

    在大部分情况下,对执行速度而言,StringBuilder > StringBuffer。因为前者不需要考虑线程安全问题。

三、三兄弟的优缺点  

    String 类型和StringBuffer的主要性能区别:String是不可变的对象, 因此在每次对String 类型进行改变的时候,都会生成一个新的 String 对象,然后将指针指向新的 String 对象,所以经常改变内容的字符串最好不要用 String ,因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后, JVM 的 GC 就会开始工作,性能就会降低。

   使用 StringBuffer 类时,每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象并改变对象引用。所以多数情况下推荐使用 StringBuffer ,特别是字符串对象经常改变的情况下。

   在某些特别情况下, String 对象的字符串拼接其实是被 Java Compiler 编译成了 StringBuffer 对象的拼接,所以这些时候 String 对象的速度并不会比 StringBuffer 对象慢,例如:

<span style="font-family:FangSong_GB2312;font-size:18px;">String s1 = “This is only a” + “ simple” + “ test”;  StringBuffer Sb = new StringBuilder(“This is only a”).append(“ simple”).append(“ test”);  </span>

   生成 String s1对象的速度并不比 StringBuffer慢。其实在Java Compiler里,自动做了如下转换:

Java Compiler直接把上述第一条语句编译为:

<span style="font-family:FangSong_GB2312;font-size:18px;">String s1 = “This is only a simple test”;  </span>

   所以速度很快。但要注意的是,如果拼接的字符串来自另外的String对象的话,Java Compiler就不会自动转换了,速度也就没那么快了。

   因此如果要操作少量的数据,使用String;

        单线程操作大量数据,使用StringBuilder;

        多线程操作大量数据,使用StringBuffer。

 

1 0