Java字符串连接

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

 

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

 1 package com.vbo.javatest;
 2 
 3 public class StringAppendTest {
 4     private int mInteger = 1;
 5     private static final int INTEGER = 1;
 6 
 7     public static void main(String[] args) {
 8         new StringAppendTest().stringAppendWithPlusSign();
 9         new StringAppendTest().stringAppendWithStringBuffer();
10         new StringAppendTest().stringAppendWithStringBuilder();
11     }
12 
13     private void stringAppendWithPlusSign() {
14         String result1 = "1" + "1";
15         String result2 = "1" + INTEGER;
16         String result3 = "1" + mInteger;
17         System.out.println(result1);
18         System.out.println(result2);
19         System.out.println(result3);
20     }
21 
22     private void stringAppendWithStringBuffer() {
23         StringBuffer result = new StringBuffer();
24         result.append("1");
25         result.append(INTEGER);
26         result.append(mInteger);
27         System.out.println(result.toString());
28     }
29 
30     private void stringAppendWithStringBuilder() {
31         StringBuilder result = new StringBuilder();
32         result.append("1");
33         result.append(INTEGER);
34         result.append(mInteger);
35         System.out.println(result.toString());
36     }
37 }

 

编译再反编译后的结果:

  1 package com.vbo.javatest;
  2 
  3 import java.io.PrintStream;
  4 
  5 public class StringAppendTest
  6 {
  7 
  8     public StringAppendTest()
  9     {
 10     //    0    0:aload_0         
 11     //    1    1:invokespecial   #13  <Method void Object()>
 12         mInteger = 1;
 13     //    2    4:aload_0         
 14     //    3    5:iconst_1        
 15     //    4    6:putfield        #15  <Field int com.vbo.javatest.StringAppendTest.mInteger>
 16     //    5    9:return          
 17     }
 18 
 19     public static void main(java.lang.String args[])
 20     {
 21         (new StringAppendTest()).stringAppendWithPlusSign();
 22     //    0    0:new             #1   <Class com.vbo.javatest.StringAppendTest>
 23     //    1    3:dup             
 24     //    2    4:invokespecial   #23  <Method void StringAppendTest()>
 25     //    3    7:invokespecial   #24  <Method void com.vbo.javatest.StringAppendTest.stringAppendWithPlusSign()>
 26         (new StringAppendTest()).stringAppendWithStringBuffer();
 27     //    4   10:new             #1   <Class com.vbo.javatest.StringAppendTest>
 28     //    5   13:dup             
 29     //    6   14:invokespecial   #23  <Method void StringAppendTest()>
 30     //    7   17:invokespecial   #27  <Method void com.vbo.javatest.StringAppendTest.stringAppendWithStringBuffer()>
 31         (new StringAppendTest()).stringAppendWithStringBuilder();
 32     //    8   20:new             #1   <Class com.vbo.javatest.StringAppendTest>
 33     //    9   23:dup             
 34     //   10   24:invokespecial   #23  <Method void StringAppendTest()>
 35     //   11   27:invokespecial   #30  <Method void com.vbo.javatest.StringAppendTest.stringAppendWithStringBuilder()>
 36     //   12   30:return          
 37     }
 38 
 39     private void stringAppendWithPlusSign()
 40     {
 41         java.lang.String result1 = "11";
 42     //    0    0:ldc1            #35  <String "11">
 43     //    1    2:astore_1        
 44         java.lang.String result2 = "11";
 45     //    2    3:ldc1            #35  <String "11">
 46     //    3    5:astore_2        
 47         java.lang.String result3 = (new StringBuilder("1")).append(mInteger).toString();
 48     //    4    6:new             #37  <Class java.lang.StringBuilder>
 49     //    5    9:dup             
 50     //    6   10:ldc1            #39  <String "1">
 51     //    7   12:invokespecial   #41  <Method void StringBuilder(java.lang.String)>
 52     //    8   15:aload_0         
 53     //    9   16:getfield        #15  <Field int com.vbo.javatest.StringAppendTest.mInteger>
 54     //   10   19:invokevirtual   #44  <Method java.lang.StringBuilder java.lang.StringBuilder.append(int)>
 55     //   11   22:invokevirtual   #48  <Method java.lang.String java.lang.StringBuilder.toString()>
 56     //   12   25:astore_3        
 57         java.lang.System.out.println(result1);
 58     //   13   26:getstatic       #52  <Field java.io.PrintStream java.lang.System.out>
 59     //   14   29:aload_1         
 60     //   15   30:invokevirtual   #58  <Method void java.io.PrintStream.println(java.lang.String)>
 61         java.lang.System.out.println(result2);
 62     //   16   33:getstatic       #52  <Field java.io.PrintStream java.lang.System.out>
 63     //   17   36:aload_2         
 64     //   18   37:invokevirtual   #58  <Method void java.io.PrintStream.println(java.lang.String)>
 65         java.lang.System.out.println(result3);
 66     //   19   40:getstatic       #52  <Field java.io.PrintStream java.lang.System.out>
 67     //   20   43:aload_3         
 68     //   21   44:invokevirtual   #58  <Method void java.io.PrintStream.println(java.lang.String)>
 69     //   22   47:return          
 70     }
 71 
 72     private void stringAppendWithStringBuffer()
 73     {
 74         java.lang.StringBuffer result = new StringBuffer();
 75     //    0    0:new             #67  <Class java.lang.StringBuffer>
 76     //    1    3:dup             
 77     //    2    4:invokespecial   #69  <Method void StringBuffer()>
 78     //    3    7:astore_1        
 79         result.append("1");
 80     //    4    8:aload_1         
 81     //    5    9:ldc1            #39  <String "1">
 82     //    6   11:invokevirtual   #70  <Method java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.String)>
 83     //    7   14:pop             
 84         result.append(1);
 85     //    8   15:aload_1         
 86     //    9   16:iconst_1        
 87     //   10   17:invokevirtual   #73  <Method java.lang.StringBuffer java.lang.StringBuffer.append(int)>
 88     //   11   20:pop             
 89         result.append(mInteger);
 90     //   12   21:aload_1         
 91     //   13   22:aload_0         
 92     //   14   23:getfield        #15  <Field int com.vbo.javatest.StringAppendTest.mInteger>
 93     //   15   26:invokevirtual   #73  <Method java.lang.StringBuffer java.lang.StringBuffer.append(int)>
 94     //   16   29:pop             
 95         java.lang.System.out.println(result.toString());
 96     //   17   30:getstatic       #52  <Field java.io.PrintStream java.lang.System.out>
 97     //   18   33:aload_1         
 98     //   19   34:invokevirtual   #76  <Method java.lang.String java.lang.StringBuffer.toString()>
 99     //   20   37:invokevirtual   #58  <Method void java.io.PrintStream.println(java.lang.String)>
100     //   21   40:return          
101     }
102 
103     private void stringAppendWithStringBuilder()
104     {
105         java.lang.StringBuilder result = new StringBuilder();
106     //    0    0:new             #37  <Class java.lang.StringBuilder>
107     //    1    3:dup             
108     //    2    4:invokespecial   #79  <Method void StringBuilder()>
109     //    3    7:astore_1        
110         result.append("1");
111     //    4    8:aload_1         
112     //    5    9:ldc1            #39  <String "1">
113     //    6   11:invokevirtual   #80  <Method java.lang.StringBuilder java.lang.StringBuilder.append(java.lang.String)>
114     //    7   14:pop             
115         result.append(1);
116     //    8   15:aload_1         
117     //    9   16:iconst_1        
118     //   10   17:invokevirtual   #44  <Method java.lang.StringBuilder java.lang.StringBuilder.append(int)>
119     //   11   20:pop             
120         result.append(mInteger);
121     //   12   21:aload_1         
122     //   13   22:aload_0         
123     //   14   23:getfield        #15  <Field int com.vbo.javatest.StringAppendTest.mInteger>
124     //   15   26:invokevirtual   #44  <Method java.lang.StringBuilder java.lang.StringBuilder.append(int)>
125     //   16   29:pop             
126         java.lang.System.out.println(result.toString());
127     //   17   30:getstatic       #52  <Field java.io.PrintStream java.lang.System.out>
128     //   18   33:aload_1         
129     //   19   34:invokevirtual   #48  <Method java.lang.String java.lang.StringBuilder.toString()>
130     //   20   37:invokevirtual   #58  <Method void java.io.PrintStream.println(java.lang.String)>
131     //   21   40:return          
132     }
133 
134     private int mInteger;
135     private static final int INTEGER = 1;
136 }

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

当相加的字符串中包含不确定量(变量)时(情况2),编译器将“+”编译为StringBuilder实现,这样看起来两者没有本质区别,我们可以抽某些人的嘴巴了么?Too Simple, sometimes navie!

第三种情况:

1 String result = null;
2 for (int i = 0; i < 100; i++) {
3     result += mInteger;
4 }
5 
6 StringBuilder result = new StringBuilder();
7 for (int i = 0; i < 100; i++) {
8     result.append(mInteger);
9 }

编译再反编译后的结果:

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

哦!!!"大牛"们说的是这个意思。用"+"导致new 了100个StringBuilder!

我向来不惮以最好的善意揣测“大牛”:他们没有时间给出论据,只给出了论点,他们给出教诲时没有时间给出前提条件。

posted @ 2012-06-08 11:39  vbo  阅读(8196)  评论(5编辑  收藏  举报