关于 String,StringBuilder,StringBuffer 的讨论,已有很多文章;在这里,我希望能刨根问底,更进一步的理解其中的原理。

  • String

   String 是final类型,不可继承的类;内部存储是字符数组(char[]),也是final ,不可更改;

/** 源码中 String 类的声明 */
public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];

 

  我们知道 final 修饰变量,只能被赋值一次,赋值成功后,不可再重新赋值。这意味怎么什么呢?先看一下下面的例子:

public static void main(String[] args) {
        String a = "sdfsdklfjdskl1245";
        String b = "1234567489123";
        String c = a + b;
        System.out.println(c);
    }

  这里声明三个字符常量,在初始化时,a和b是字符数组常量,而c则是两个常量字符数组的连接;不信请看编译后的代码:

F:\opensource\panda-demo\src\test\java>javap -c Test
Compiled from "Test.java"
public class Test {
  public Test();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: ldc           #2                  // String sdfsdklfjdskl1245
       2: astore_1
       3: ldc           #3                  // String 1234567489123
       5: astore_2
       6: aload_1
       7: aload_2
       8: invokedynamic #4,  0              // InvokeDynamic #0:makeConcatWithConstants:(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
      13: astore_3
      14: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;
      17: aload_3
      18: invokevirtual #6                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      21: return
}

F:\opensource\panda-demo\src\test\java>

(小弟知识范围有限,若上述代码解读有误,还请指正,不胜感激)

  所以 String 字符串的拼接,是不会有性能问题的;那有些面试题说的字符串拼接性能低效又是怎么回事呢?请看下面例子:

public class Test {

    public static void main(String[] args) {
        String a = "123456";
        for (int i=0; i<10; i++) {
            a += "dfdsfdsfds";
        }
        System.out.println(a);
    }
}

  上面代码中,我们初始化了常量a,并且在循环里面做了多次字符串的拼接,最终a的指针地址指向了字符串拼接后的结果。这里存在以下问题:

  1、字符拼接过程产生了大量的字符数组;我们通过第一个例子,知道了字符串底层是字符数组存储,且是不可变的,而字符串拼接是字符数组连接的副本。

  2、大量指针的操作;循环中,需要不断调整变量a的值,指向连接后的数组,难免有指针的操作。

  综上,String 字符串拼接性能低效,是和 StringBuilder、StringBuffer 做比较的,当然,没有比较,也就没有低效和高效的说法。

  再看看 StringBuilder 和 StringBuffer 内部又是怎么玩的。

  • StringBuilder
  • StringBuffer

版权声明:本文为rabbitblog原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/rabbitblog/p/8820771.html