Java字符串连接

声明:本人菜鸟,大牛请无视。

 

某些大牛教导我们,Java中字符串拼接的话要用StringBuilder或者StringBuffer.不要用"+",会有性能问题。但我看Android的源码,Google的工程师遍地都是"+".困惑了。So,验证。

 
 public class StringAppendTest {
     private int mInteger = 1;
     private static final int INTEGER = 1;
 
     public static void main(String[] args) {
         new StringAppendTest().stringAppendWithPlusSign();
         new StringAppendTest().stringAppendWithStringBuffer();
         new StringAppendTest().stringAppendWithStringBuilder();
     }
 
     private void stringAppendWithPlusSign() {
         String result1 = "1" + "1";
         String result2 = "1" + INTEGER;
         String result3 = "1" + mInteger;
         System.out.println(result1);
         System.out.println(result2);
         System.out.println(result3);
     }
 
     private void stringAppendWithStringBuffer() {
         StringBuffer result = new StringBuffer();
         result.append("1");
         result.append(INTEGER);
         result.append(mInteger);
         System.out.println(result.toString());
     }
 
     private void stringAppendWithStringBuilder() {
         StringBuilder result = new StringBuilder();
         result.append("1");
         result.append(INTEGER);
         result.append(mInteger);
         System.out.println(result.toString());
     }
 }

编译再反编译后的结果:

package com.vbo.javatest;
 
 import java.io.PrintStream;
 
 public class StringAppendTest
 {
 
     public StringAppendTest()
     {
     //    0    0:aload_0         
     //    1    1:invokespecial   #13  <Method void Object()>
         mInteger = 1;
     //    2    4:aload_0         
     //    3    5:iconst_1        
     //    4    6:putfield        #15  <Field int com.vbo.javatest.StringAppendTest.mInteger>
     //    5    9:return          
     }
 
     public static void main(java.lang.String args[])
     {
         (new StringAppendTest()).stringAppendWithPlusSign();
     //    0    0:new             #1   <Class com.vbo.javatest.StringAppendTest>
     //    1    3:dup             
     //    2    4:invokespecial   #23  <Method void StringAppendTest()>
     //    3    7:invokespecial   #24  <Method void com.vbo.javatest.StringAppendTest.stringAppendWithPlusSign()>
         (new StringAppendTest()).stringAppendWithStringBuffer();
     //    4   10:new             #1   <Class com.vbo.javatest.StringAppendTest>
     //    5   13:dup             
     //    6   14:invokespecial   #23  <Method void StringAppendTest()>
     //    7   17:invokespecial   #27  <Method void com.vbo.javatest.StringAppendTest.stringAppendWithStringBuffer()>
         (new StringAppendTest()).stringAppendWithStringBuilder();
     //    8   20:new             #1   <Class com.vbo.javatest.StringAppendTest>
     //    9   23:dup             
     //   10   24:invokespecial   #23  <Method void StringAppendTest()>
     //   11   27:invokespecial   #30  <Method void com.vbo.javatest.StringAppendTest.stringAppendWithStringBuilder()>
     //   12   30:return          
     }
 
     private void stringAppendWithPlusSign()
     {
         java.lang.String result1 = "11";
     //    0    0:ldc1            #35  <String "11">
     //    1    2:astore_1        
         java.lang.String result2 = "11";
     //    2    3:ldc1            #35  <String "11">
     //    3    5:astore_2        
         java.lang.String result3 = (new StringBuilder("1")).append(mInteger).toString();
     //    4    6:new             #37  <Class java.lang.StringBuilder>
     //    5    9:dup             
     //    6   10:ldc1            #39  <String "1">
     //    7   12:invokespecial   #41  <Method void StringBuilder(java.lang.String)>
     //    8   15:aload_0         
     //    9   16:getfield        #15  <Field int com.vbo.javatest.StringAppendTest.mInteger>
     //   10   19:invokevirtual   #44  <Method java.lang.StringBuilder java.lang.StringBuilder.append(int)>
     //   11   22:invokevirtual   #48  <Method java.lang.String java.lang.StringBuilder.toString()>
     //   12   25:astore_3        
         java.lang.System.out.println(result1);
     //   13   26:getstatic       #52  <Field java.io.PrintStream java.lang.System.out>
     //   14   29:aload_1         
     //   15   30:invokevirtual   #58  <Method void java.io.PrintStream.println(java.lang.String)>
         java.lang.System.out.println(result2);
     //   16   33:getstatic       #52  <Field java.io.PrintStream java.lang.System.out>
     //   17   36:aload_2         
     //   18   37:invokevirtual   #58  <Method void java.io.PrintStream.println(java.lang.String)>
         java.lang.System.out.println(result3);
     //   19   40:getstatic       #52  <Field java.io.PrintStream java.lang.System.out>
     //   20   43:aload_3         
     //   21   44:invokevirtual   #58  <Method void java.io.PrintStream.println(java.lang.String)>
     //   22   47:return          
     }
 
     private void stringAppendWithStringBuffer()
     {
         java.lang.StringBuffer result = new StringBuffer();
     //    0    0:new             #67  <Class java.lang.StringBuffer>
     //    1    3:dup             
     //    2    4:invokespecial   #69  <Method void StringBuffer()>
     //    3    7:astore_1        
         result.append("1");
     //    4    8:aload_1         
     //    5    9:ldc1            #39  <String "1">
     //    6   11:invokevirtual   #70  <Method java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.String)>
     //    7   14:pop             
         result.append(1);
     //    8   15:aload_1         
     //    9   16:iconst_1        
     //   10   17:invokevirtual   #73  <Method java.lang.StringBuffer java.lang.StringBuffer.append(int)>
     //   11   20:pop             
         result.append(mInteger);
     //   12   21:aload_1         
     //   13   22:aload_0         
     //   14   23:getfield        #15  <Field int com.vbo.javatest.StringAppendTest.mInteger>
     //   15   26:invokevirtual   #73  <Method java.lang.StringBuffer java.lang.StringBuffer.append(int)>
     //   16   29:pop             
         java.lang.System.out.println(result.toString());
     //   17   30:getstatic       #52  <Field java.io.PrintStream java.lang.System.out>
     //   18   33:aload_1         
     //   19   34:invokevirtual   #76  <Method java.lang.String java.lang.StringBuffer.toString()>
     //   20   37:invokevirtual   #58  <Method void java.io.PrintStream.println(java.lang.String)>
     //   21   40:return          
     }
 
     private void stringAppendWithStringBuilder()
     {
         java.lang.StringBuilder result = new StringBuilder();
     //    0    0:new             #37  <Class java.lang.StringBuilder>
     //    1    3:dup             
     //    2    4:invokespecial   #79  <Method void StringBuilder()>
     //    3    7:astore_1        
         result.append("1");
     //    4    8:aload_1         
     //    5    9:ldc1            #39  <String "1">
     //    6   11:invokevirtual   #80  <Method java.lang.StringBuilder java.lang.StringBuilder.append(java.lang.String)>
     //    7   14:pop             
         result.append(1);
     //    8   15:aload_1         
     //    9   16:iconst_1        
     //   10   17:invokevirtual   #44  <Method java.lang.StringBuilder java.lang.StringBuilder.append(int)>
     //   11   20:pop             
         result.append(mInteger);
     //   12   21:aload_1         
     //   13   22:aload_0         
     //   14   23:getfield        #15  <Field int com.vbo.javatest.StringAppendTest.mInteger>
     //   15   26:invokevirtual   #44  <Method java.lang.StringBuilder java.lang.StringBuilder.append(int)>
     //   16   29:pop             
         java.lang.System.out.println(result.toString());
     //   17   30:getstatic       #52  <Field java.io.PrintStream java.lang.System.out>
     //   18   33:aload_1         
     //   19   34:invokevirtual   #48  <Method java.lang.String java.lang.StringBuilder.toString()>
     //   20   37:invokevirtual   #58  <Method void java.io.PrintStream.println(java.lang.String)>
     //   21   40:return          
     }
 
     private int mInteger;
     private static final int INTEGER = 1;
 }

当多个确定量(常量)字符串相加时(情况1),编译器直接将它们编辑为相加后的字符串,这样的情况下用“+”比StringBuilder运行时效率更高。

当相加的字符串中包含不确定量(变量)时(情况2),编译器将“+”编译为StringBuilder实现,这样看起来两者没有本质区别? No!

第三种情况:

String result = null;
 for (int i = 0; i < 100; i++) {
     result += mInteger;
 }
 
 StringBuilder result = new StringBuilder();
 for (int i = 0; i < 100; i++) {
     result.append(mInteger);
 }

编译再反编译后的结果:

private void stringAppendInLoop()
     {
         java.lang.String result = null;
     //    0    0:aconst_null     
     //    1    1:astore_1        
         for(int i = 0; i < 100; i++)
     //*   2    2:iconst_0        
     //*   3    3:istore_2        
     //*   4    4:goto            32
             result = (new StringBuilder(java.lang.String.valueOf(result))).append(mInteger).toString();
     //    5    7:new             #40  <Class java.lang.StringBuilder>
     //    6   10:dup             
     //    7   11:aload_1         
     //    8   12:invokestatic    #87  <Method java.lang.String java.lang.String.valueOf(java.lang.Object)>
     //    9   15:invokespecial   #44  <Method void StringBuilder(java.lang.String)>
     //   10   18:aload_0         
     //   11   19:getfield        #15  <Field int com.vbo.javatest.StringAppendTest.mInteger>
     //   12   22:invokevirtual   #47  <Method java.lang.StringBuilder java.lang.StringBuilder.append(int)>
     //   13   25:invokevirtual   #51  <Method java.lang.String java.lang.StringBuilder.toString()>
     //   14   28:astore_1        
 
     //   15   29:iinc            2  1
     //   16   32:iload_2         
     //   17   33:bipush          100
     //   18   35:icmplt          7
         java.lang.StringBuilder result1 = new StringBuilder();
     //   19   38:new             #40  <Class java.lang.StringBuilder>
     //   20   41:dup             
     //   21   42:invokespecial   #82  <Method void StringBuilder()>
     //   22   45:astore_2        
         for(int i = 0; i < 100; i++)
     //*  23   46:iconst_0        
     //*  24   47:istore_3        
     //*  25   48:goto            63
             result1.append(mInteger);
     //   26   51:aload_2         
     //   27   52:aload_0         
     //   28   53:getfield        #15  <Field int com.vbo.javatest.StringAppendTest.mInteger>
     //   29   56:invokevirtual   #47  <Method java.lang.StringBuilder java.lang.StringBuilder.append(int)>
     //   30   59:pop             
 
     //   31   60:iinc            3  1
     //   32   63:iload_3         
     //   33   64:bipush          100
     //   34   66:icmplt          51
     //   35   69:return          
     }

用"+"导致new 了100个StringBuilder!

所以给出论点的同时需要给出论据,选择处理方式时需要考虑前提条件(不同场景)

你可能感兴趣的:(java,字符串连接,Java字符串连接)