Java浅谈String、StringBuffer和StringBuilder

  Java 提供了StringStringBufferStringBuilder这几个类来封装字符串,同时也提供了一系列的方法来操作这些对象。

String

  关于String类,JDK源码当中是这样的(我这里使用的是JDK1.8):

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];
    /** Cache the hash code for the string */
    private int hash; // Default to 0
    /** use serialVersionUID from JDK 1.0.2 for interoperability */
    private static final long serialVersionUID = -6849794470754667710L;
    ......
}

  可以看到String类是final修饰的类。在Java中,我们知道,被final修饰的类是不允许被继承的,而且该类中的成员方法都默认为是final方法。
  所以我们说String对象是不可变的,具有只读特性,也因此它是可以共享的。也正因为String对象是不可变的,我们在对String对象的进行任何操作的时候,其都会为我们生成一个新的String对象,并将原本的对象引用(或者新声明的对象引用)指向新的String对象,而原本的String对象并没有丝毫的改变。

  下面来看段代码:

public class StringTest {
      public static void main(String[] args) {
            String nameXX = "bigsea";
            // 新生成了对象并指向新声明的引用
            String nameDX = nameXX.toUpperCase();
            System.out.println(nameXX);         // 结果为:  bigsea
            System.out.println(nameDX);         // 结果为:  BIGSEA
      }
}

  以上代码在调用String对象toUpperCase()方法的过程中,生成了一个新的String对象,并指向了新声明的nameDX引用,并不影响原本的nameXX。

  由于String是不可变的,所以在操作的过程当中会额外的产生许多的临时变量,从而带来一定的效率问题。然而,使用StringBuffer和StringBuilder可以避免这个问题。

  我们先来看看以下的代码:

public class StringTest {

      private static int count = 66666;

      public static void stringTest() {
            String str = "java Developer";
            long start = System.currentTimeMillis();
            for (int i = 0; i < count; i++) {
                  str += "bigsea";
            }
            long end = System.currentTimeMillis();
            System.out.println("String类型使用的时间:" + (end - start) + "毫秒");
      }

      public static void stringBufferTest() {
            StringBuffer sb = new StringBuffer("java Developer");
            long start = System.currentTimeMillis();
            for (int i = 0; i < count; i++) {
                  sb.append("bigsea");
            }
            long end = System.currentTimeMillis();
            System.out.println("StringBuffer类型使用的时间:" + (end - start) + "毫秒");
      }

      public static void stringBuilderTest() {
            StringBuilder sb = new StringBuilder("java Developer");
            long start = System.currentTimeMillis();
            for (int i = 0; i < count; i++) {
                  sb.append("bigsea");
            }
            long end = System.currentTimeMillis();
            System.out.println("StringBuilder类型使用的时间:" + (end - start) + "毫秒");
      }

      public static void main(String[] args) {
            StringTest.stringTest();                  // 结果为: String类型使用的时间:6720毫秒
            StringTest.stringBufferTest();            // 结果为: StringBuffer类型使用的时间:3毫秒
            StringTest.stringBuilderTest();           // 结果为: StringBuilder类型使用的时间:2毫秒
      }
}

  从上述代码中我们看到,在频繁操作字符串的时候,StringBuffer和StringBuilder在一定程度上为我们提升了效率。

StringBuffer

  StringBuffer的字符序列是可变的。它是一个类似String字符串的缓冲区。虽然在任意的时间点上它都包含某种特定的字符串序列,但通过某些方法的调用就可以改变该序列的长度和内容,包括append()、insert()、reverse()、setCharAt()、setLength()等方法。当通过StringBuffer生成了我们所需要的字符串,我们可以调用其本身的toString()方法将其转变成为一个String对象。

StringBuffer上的主要操作是append和insert方法,可重载这些方法,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符追加或插入到字符串缓冲区中。append方法始终将这些字符添加到缓冲区的末端;而 insert方法则在指定的点添加字符。

举个例子,代码如下:

public class Test {
    public static void main(String[] args) {
        StringBuffer sb1 = new StringBuffer("see");
        StringBuffer sb2 = new StringBuffer("see");

        sb1.append("bigsea");
        sb2.insert(3, "bigsea");

        System.out.println(sb1);    // 结果为: seebigsea
        System.out.println(sb2);    // 结果为: seebigsea
    }
}

sb1对象引用引用一个当前内容为“see”的字符串缓冲区对象,那么调用该对象的这个方法sb1.append(“bigsea”)会使字符串缓冲区包含”seebigsea”。
sb2对象引用也引用一个当前内容为“see”的字符串缓冲区对象,那么调用该对象的这个方法sb2.insert(3, “bigsea”) 将更改字符串缓冲区,也会使之包含 “seebigsea”。

StringBuilder

  至于StringBuilder这个类是在JDK1.5新增加的。查看下这两者的JDK我们不难发现这两个类是基本相类似的,两个类的构造器和方法也是基本的相同的。两者之间的区别在于StringBuffer是线程安全的,需要执行同步操作,因此开销也会大些;而StringBuilder是线程不安全的,支持所有的相同操作,不需要执行同步,所以它的速度更快些。

使用情况

关于三者的执行效率,在绝大多数的情况下 StringBuilder > StringBuffer > String

具体的还需要根据不同的情况来进行选择使用:
  1.在字符串操作或者改动比较少的情况下,还是建议使用String;
  2.在字符串操作或者改动比较多的情况下,建议使用StringBuilder;但是如果中间过程涉及到了多线程,建议还是使用StringBuffer。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值