入门客AI创业平台(我带你入门,你带我飞行)
博文笔记

java字符串连接问题

创建时间:2018-04-04 投稿人: 浏览次数:177

前景

在java核心技术 卷1上有这样一段话构建字符串的时候,每次使用+号都会产生一个新的String对象,会浪费资源,最好用StringBuilder。因为那本书的版本是JDK8的,所有这句话是对的,并且网上关于它的讲解也很对,下面附上一个很好的连接
https://blog.csdn.net/m0_37589327/article/details/78605268
就JDK 8而言,它的讲解是对的。当+号在不同语句中的时候,每次会new一下,创建新的对象,并且javac会调用StringBuilder。append这个方法进行+的优化。但是当我在JDK9上的时候发现了不同的答案,是JDK9的新特性,下面放上我的实验结果图,与JDK有不同之处

问题

测试代码:


public class test {
    public static void main(String[] args)
    {
        String str = "";
        long start = System.currentTimeMillis();
        for(int i=0; i<100000; i++)
            str += "a";
        long end = System.currentTimeMillis();
        System.out.println(end - start);

        StringBuilder sb = new StringBuilder();
        start = System.currentTimeMillis();
        for(int i=0; i<100000; i++)
            sb.append("a");
        str = sb.toString();
        end = System.currentTimeMillis();   
        System.out.println(end - start);

        String a="";
        a+="a";
        a+="a";
        a+="a";

    }
}

反编译得到的结果

dream@love_lyy:~/java/test/src$ javap -c test.class 
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
       2: astore_1
       3: invokestatic  #3                  // Method java/lang/System.currentTimeMillis:()J
       6: lstore_2
       7: iconst_0
       8: istore        4
      10: iload         4
      12: ldc           #4                  // int 100000
      14: if_icmpge     30
      17: aload_1
      18: invokedynamic #5,  0              // InvokeDynamic #0:makeConcatWithConstants:(Ljava/lang/String;)Ljava/lang/String;
      23: astore_1
      24: iinc          4, 1
      27: goto          10
      30: invokestatic  #3                  // Method java/lang/System.currentTimeMillis:()J
      33: lstore        4
      35: getstatic     #6                  // Field java/lang/System.out:Ljava/io/PrintStream;
      38: lload         4
      40: lload_2
      41: lsub
      42: invokevirtual #7                  // Method java/io/PrintStream.println:(J)V
      45: new           #8                  // class java/lang/StringBuilder
      48: dup
      49: invokespecial #9                  // Method java/lang/StringBuilder."<init>":()V
      52: astore        6
      54: invokestatic  #3                  // Method java/lang/System.currentTimeMillis:()J
      57: lstore_2
      58: iconst_0
      59: istore        7
      61: iload         7
      63: ldc           #4                  // int 100000
      65: if_icmpge     82
      68: aload         6
      70: ldc           #10                 // String a
      72: invokevirtual #11                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      75: pop
      76: iinc          7, 1
      79: goto          61
      82: aload         6
      84: invokevirtual #12                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      87: astore_1
      88: invokestatic  #3                  // Method java/lang/System.currentTimeMillis:()J
      91: lstore        4
      93: getstatic     #6                  // Field java/lang/System.out:Ljava/io/PrintStream;
      96: lload         4
      98: lload_2
      99: lsub
     100: invokevirtual #7                  // Method java/io/PrintStream.println:(J)V
     103: ldc           #2                  // String
     105: astore        7
     107: aload         7
     109: invokedynamic #5,  0              // InvokeDynamic #0:makeConcatWithConstants:(Ljava/lang/String;)Ljava/lang/String;
     114: astore        7
     116: aload         7
     118: invokedynamic #5,  0              // InvokeDynamic #0:makeConcatWithConstants:(Ljava/lang/String;)Ljava/lang/String;
     123: astore        7
     125: aload         7
     127: invokedynamic #5,  0              // InvokeDynamic #0:makeConcatWithConstants:(Ljava/lang/String;)Ljava/lang/String;
     132: astore        7
     134: aconst_null
     135: astore        8
     137: aload         8
     139: invokedynamic #13,  0             // InvokeDynamic #1:makeConcatWithConstants:(Ljava/lang/String;)Ljava/lang/String;
     144: astore        8
     146: getstatic     #6                  // Field java/lang/System.out:Ljava/io/PrintStream;
     149: aload         8
     151: invokevirtual #14                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
     154: return
}

理解

由于中文的我没有搜到这个答案,在stackoverflow和jdk9 API上我都看了一下这个函数,先看看API

API

这里写图片描述
API上对这两个方法的描述是:促进了最佳的字符串拼接的方法,能够有效地连接已知数量的、具有已知类型的参数。。。等于没讲。之后看看stackoverflow上怎么讲的。

stackoverflow

private enum Strategy {
    /**
     * Bytecode generator, calling into {@link java.lang.StringBuilder}.
     */
    BC_SB,

    /**
     * Bytecode generator, calling into {@link java.lang.StringBuilder};
     * but trying to estimate the required storage.
     */
    BC_SB_SIZED,

    /**
     * Bytecode generator, calling into {@link java.lang.StringBuilder};
     * but computing the required storage exactly.
     */
    BC_SB_SIZED_EXACT,

    /**
     * MethodHandle-based generator, that in the end calls into {@link java.lang.StringBuilder}.
     * This strategy also tries to estimate the required storage.
     */
    MH_SB_SIZED,

    /**
     * MethodHandle-based generator, that in the end calls into {@link java.lang.StringBuilder}.
     * This strategy also estimate the required storage exactly.
     */
    MH_SB_SIZED_EXACT,

    /**
     * MethodHandle-based generator, that constructs its own byte[] array from
     * the arguments. It computes the required storage exactly.
     */
    MH_INLINE_SIZED_EXACT
}

简而言之,一共提供了6种方法供它来动态选择,至于如何动态选择,我这个新手是搞不懂的了 - -。前5种是SB——StringBuilder,可以看出来的是,并没有舍弃StringBuilder这个方法,而是更加细分了它们,达到一个更好的效果。(纯属个人理解,因为才学java一周。。。)我实现的这个测试代码的结论我觉得暂时是和JDK8测试一致的。

总结

对于我这个新手其实只要知道,JDK9 延续了JDK8的好处,并且还实现了再优化!+号连接字符串,在不同语句中,是会创建新的String对象的,就是多次做了连接,而不是在一句话里面连接好。StringBuilder优就优在这。更深入的学习,对于小白来说,不用知道。等长大了再慢慢学咯~

阅读更多
声明:该文观点仅代表作者本人,入门客AI创业平台信息发布平台仅提供信息存储空间服务,如有疑问请联系rumenke@qq.com。
  • 上一篇:没有了
  • 下一篇:没有了
未上传头像