zoukankan      html  css  js  c++  java
  • Java的字符串连接符(+)

    在Java中字符串是一个常用的东西,而其一个常用的操作是字符串的拼接,Java对此提供了一种非常直观的操作方式——即 + 操作符。

    String str0 = "a";
    String str1 = str0 + "b";

    如上的程序片段就实现了一个字符串的拼接,可以看到整个描述非常简洁,一目了然。学习Java的时候,这是接触到的第一种拼接字符串的方式,先入为主的印象会让你在以后需要拼接字符串时第一时间想到它,但是,你会听到大家都说:拼接大量的字符串时使用StringBuilder更好,这是为什么呢?


    让我们看看编译器是怎么处理 + 操作符的。下面是上一个程序片段编译后的字节码指令:

      public static void main(java.lang.String[]);
        Code:
           0: ldc           #2                  // String a
           2: astore_1
           3: new           #3                  // class java/lang/StringBuilder
           6: dup
           7: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
          10: aload_1
          11: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
          14: ldc           #6                  // String b
          16: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
          19: invokevirtual #7                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
          22: astore_2
          23: return
    }

    通过阅读这段字节码,可以发现,我们的+拼接操作实际上被编译器理解成了这个样子:

    String str0 = "a";
    StringBuilder sb = new StringBuilder();
    sb.append(str0).append("b");
    String str1 = sb.toString();

    中间多出来了一个StringBuilder对象,这是一个临时对象。


    假设我们现在有这样一段程序片段:

    String str0 = "a";
    for (int i = 0; i < 10000; i++) {    
          str0 += "a";
    }

    再来看看编译后的字节码:

      public static void main(java.lang.String[]);
        Code:
           0: ldc           #2                  // String a
           2: astore_1
           3: iconst_0
           4: istore_2
           5: iload_2
           6: sipush        10000
           9: if_icmpge     38
          12: new           #3                  // class java/lang/StringBuilder
          15: dup
          16: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
          19: aload_1
          20: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
          23: ldc           #2                  // String a
          25: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
          28: invokevirtual #6                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
          31: astore_1
          32: iinc          2, 1
          35: goto          5
          38: return
    }
    

    5~35是我们的循环体,在循环体里面,每次拼接都会生成一个StringBuilder的临时对象,那么这个程序片段执行下去就会产生10000个StringBuilder的临时对象,这10000个临时对象都是必要的吗?显然不是,我们可以在循环体外直接创建一个StringBuilder对象,然后在循环体中通过append方法拼接字符串,这样就省下了创建并回收10000个临时对象的消耗。


    所以,在需要拼接大量字符串时,还是使用StringBuilder对象为好。

  • 相关阅读:
    Beego快速入门
    Ubuntu常用配置
    软件过程改进练习题
    将博客搬至CSDN
    【PTA】04-树4 是否同一棵二叉搜索树
    【PTA】03-树1 树的同构
    【转】面试还搞不懂redis,快看看这40道Redis面试题(含答案和思维导图)
    数据挖掘--聚类算法对比
    数据挖掘--模型挖掘之聚类
    数据挖掘--OPTICS
  • 原文地址:https://www.cnblogs.com/read-the-spring-and-autumn-annals-in-night/p/12041948.html
Copyright © 2011-2022 走看看