大家都知道String+String会开销额外的系统资源,粗略的原因是String是不可变类,每一步操作都会返回新的String变量,占用空间及时间。
其实我的理解不是这样的,我们来看看String+的底层实现。

测试案例

public static void main(String[] args) {
String a = "a";
StringBuilder b = new StringBuilder("b");
StringBuffer c = new StringBuffer("c");
long star = System.currentTimeMillis();
for(int i=0;i<200000;i++){
a+="a";
}
long end = System.currentTimeMillis();
System.out.println("String:"+(end-star)); star = System.currentTimeMillis();
for(int i=0;i<200000;i++){
b.append("b");
}
end = System.currentTimeMillis();
System.out.println("StringBuilder:"+(end-star)); star = System.currentTimeMillis();
for(int i=0;i<200000;i++){
c.append("c");
}
end = System.currentTimeMillis();
System.out.println("StringBuffer:"+(end-star));
}

测试结果

String:17735
StringBuilder:6
StringBuffer:7

测试结论
String+ 确实占用了太多的资源,处理效率非常低下。StringBuilder比StringBuffer更新了同步方法,性能有所提升。

原因分析

我用javap -verbose 查看已经编译好的class文件发现:

public static void main(java.lang.String[]);
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=6, locals=9, args_size=1
0: ldc #16 // String a
2: astore_1
3: new #18 // class java/lang/StringBuilder
6: dup
7: ldc #20 // String b
9: invokespecial #22 // Method java/lang/StringBuilder.
<init>":(Ljava/lang/String;)V
12: astore_2
13: new #25 // class java/lang/StringBuffer
16: dup
17: ldc #27 // String c
19: invokespecial #29 // Method java/lang/StringBuffer."
init>":(Ljava/lang/String;)V
22: astore_3
23: invokestatic #30 // Method java/lang/System.current
imeMillis:()J
26: lstore 4
28: iconst_0
29: istore 6
31: goto 57
34: new #18 // class java/lang/StringBuilder
37: dup
38: aload_1
39: invokestatic #36 // Method java/lang/String.valueOf
(Ljava/lang/Object;)Ljava/lang/String;
42: invokespecial #22 // Method java/lang/StringBuilder.
<init>":(Ljava/lang/String;)V
45: ldc #16 // String a
47: invokevirtual #42 // Method java/lang/StringBuilder.
ppend:(Ljava/lang/String;)Ljava/lang/StringBuilder;
50: invokevirtual #46 // Method java/lang/StringBuilder.
oString:()Ljava/lang/String;
53: astore_1
54: iinc 6, 1
57: iload 6
59: ldc #50 // int 100000
61: if_icmplt 34
64: invokestatic #30 // Method java/lang/System.current
imeMillis:()J
67: lstore 6
69: getstatic #51 // Field java/lang/System.out:Ljav
/io/PrintStream;
72: new #18 // class java/lang/StringBuilder
75: dup
76: ldc #55 // String String:
78: invokespecial #22 // Method java/lang/StringBuilder.
<init>":(Ljava/lang/String;)V
81: lload 6
83: lload 4
85: lsub
86: invokevirtual #57 // Method java/lang/StringBuilder.
ppend:(J)Ljava/lang/StringBuilder;
89: invokevirtual #46 // Method java/lang/StringBuilder.
oString:()Ljava/lang/String;
92: invokevirtual #60 // Method java/io/PrintStream.prin
ln:(Ljava/lang/String;)V
95: invokestatic #30 // Method java/lang/System.current
imeMillis:()J
98: lstore 4
100: iconst_0
101: istore 8
103: goto 116
106: aload_2
107: ldc #20 // String b
109: invokevirtual #42 // Method java/lang/StringBuilder.
ppend:(Ljava/lang/String;)Ljava/lang/StringBuilder;
112: pop
113: iinc 8, 1
116: iload 8
118: ldc #50 // int 100000
120: if_icmplt 106
123: invokestatic #30 // Method java/lang/System.current
imeMillis:()J
126: lstore 6
128: getstatic #51 // Field java/lang/System.out:Ljav
/io/PrintStream;
131: new #18 // class java/lang/StringBuilder
134: dup
135: ldc #65 // String StringBuilder:
137: invokespecial #22 // Method java/lang/StringBuilder.
<init>":(Ljava/lang/String;)V
140: lload 6
142: lload 4
144: lsub
145: invokevirtual #57 // Method java/lang/StringBuilder.
ppend:(J)Ljava/lang/StringBuilder;
148: invokevirtual #46 // Method java/lang/StringBuilder.
oString:()Ljava/lang/String;
151: invokevirtual #60 // Method java/io/PrintStream.prin
ln:(Ljava/lang/String;)V
154: invokestatic #30 // Method java/lang/System.current
imeMillis:()J
157: lstore 4
159: iconst_0
160: istore 8
162: goto 175
165: aload_3
166: ldc #27 // String c
168: invokevirtual #67 // Method java/lang/StringBuffer.a
pend:(Ljava/lang/String;)Ljava/lang/StringBuffer;
171: pop
172: iinc 8, 1
175: iload 8
177: ldc #50 // int 100000
179: if_icmplt 165
182: invokestatic #30 // Method java/lang/System.current
imeMillis:()J
185: lstore 6
187: getstatic #51 // Field java/lang/System.out:Ljav
/io/PrintStream;
190: new #18 // class java/lang/StringBuilder
193: dup
194: ldc #70 // String StringBuffer:
196: invokespecial #22 // Method java/lang/StringBuilder.
<init>":(Ljava/lang/String;)V
199: lload 6
201: lload 4
203: lsub
204: invokevirtual #57 // Method java/lang/StringBuilder.
ppend:(J)Ljava/lang/StringBuilder;
207: invokevirtual #46 // Method java/lang/StringBuilder.
oString:()Ljava/lang/String;
210: invokevirtual #60 // Method java/io/PrintStream.prin
ln:(Ljava/lang/String;)V
213: return

从编译的代码来看,String+的准确操作是:
new StringBuilder()

new String.valueof()

StringBuilder.<init>

StringBuilder.append()

StringBuilder.toString()

而StringBuilder的准确操作是:

StringBuilder.append()

而StringBuffer()的准确操作是:

StringBuffer.append

转自http://alqm1314-126-com.iteye.com/blog/1932879

StringBuilder的append、StringBuffer的append和String str = "a"+"b"的区别?的更多相关文章

  1. String str=new String("a")和String str = "a"有什么区别?

    问:String str=new String("a")和String str = "a"有什么区别? 答:String str = "a" ...

  2. Java中String直接赋字符串和new String的区别 如String str=new String("a")和String str = "a"有什么区别?

    百度的面试官问 String A="ABC"; String B=new String("ABC"); 这两个值,A,B 是否相等,如果都往HashSet里面放 ...

  3. Java中String str=new String("a")和String str = "a"有什么区别?

    Q: String A="ABC"; String B=new String("ABC"); 这两个值,A,B 是否相等,如果都往HashSet里面放,能放下吗 ...

  4. java中String类、StringBuilder类和StringBuffer类详解

    本位转载自http://www.cnblogs.com/dolphin0520/p/3778589.html  版权声明如下: 作者:海子 出处:http://www.cnblogs.com/dolp ...

  5. StringBuffer的append方法比“+”高效

    在字符串的连接过程中StringBuffer的效率要比String高: string操作代码: String str = new String("welcome to "); st ...

  6. StringBuilder、StringBuffer和String三者的联系和区别

    String 类    String的值是不可变的,这就导致每次对String的操作都会生成新的String对象,不仅效率低下,而且大量浪费有限的内存空间.    String a = "a ...

  7. String类、StringBuilder类、StringBuffer类

    String类是不可变类,创建了一个String对象后,该String对象中的字符序列不能被改变. StringBuilder是字符序列可变的字符串类,提供了一系列修改字符串的方法. StringBu ...

  8. JAVA String、StringBuilder、和StringBuffer的区别,及如何使用

    目录 String类 一.String类的理解和创建对象 二.String类创建的方式 两种创建String对象的区别 测试题 三.String常用方法 四.StringBuffer类 1.Strin ...

  9. StringBuilder的构造方法和append方法

    Java中StringBuilder的构造方法 StringBuilder构造方法: public StringBuilder(): 创建一个空白可变的字符串对象,不含有任何内容 public Str ...

随机推荐

  1. linux mmap 详解【转】

    转自:http://blog.chinaunix.net/uid-20321537-id-3483405.html 一.前言mmap的具体实现以前在学习内核时学习过,但是对于其中的很多函数是一知半解的 ...

  2. SHELL判断服务是不是正在运行

    使用SHELL脚本进行检查服务开启情况 #!/bin/bash #需要首先安装 yum install nmap -y #检查指定端口是否开启 function checkPortStatus() { ...

  3. PHP二维数组排序研究

    前几天在项目中碰到了一个问题,在做商城的时候,要对一个店铺里所有商品进行价格排序,而且每一种商品都拥有多个规格,要取到所有商品中所有规格的最低价和最高价,发现PHP有很友好的函数帮助我们进行筛选. 使 ...

  4. Educational Codeforces Round 39 (Rated for Div. 2) B. Weird Subtraction Process[数论/欧几里得算法]

    https://zh.wikipedia.org/wiki/%E8%BC%BE%E8%BD%89%E7%9B%B8%E9%99%A4%E6%B3%95 取模也是一样的,就当多减几次. 在欧几里得最初的 ...

  5. Codechef Chef and Triangles(离散化+区间并集)

    题目链接 Chef and Triangles 先排序,然后得到$m - 1$个区间: $(a[2] - a[1], a[2] + a[1])$ $(a[3] - a[2], a[3] + a[2]) ...

  6. Codeforces 371C Hamburgers (二分答案)

    题目链接 Hamburgers 二分答案,贪心判断即可. #include <bits/stdc++.h> using namespace std; #define REP(i,n) fo ...

  7. Maximum Product Subarray - LeetCode

    Find the contiguous subarray within an array (containing at least one number) which has the largest ...

  8. 2.搭建配置最简单的spring mvc 工程-基础版

    目标:用最少的东西,搭建可以运行的最最基础的springMvc登陆校验项目! spring 4 1.首先配置pom.xml引入spring 相关jar, 引用都有注释, 无关的可以暂时不引用. < ...

  9. vs2010下如何调试带输入参数的程序

    当main函数的输入参数为空时,我们可以很方便的通过设置断点,单步运行的方法调试,可是如果需要调试的是有输入参数的程序该怎么办呢?最终还是让我找到了: 英文版:Project -> Proper ...

  10. Retrofit 使用flatmap操作符时处理错误、异常

    在实际项目(Retrofit+RxJava框架)中,有时需要先登录,获取token后再去获取用户信息,此时我们使用flatmap操作符比较好. 在RESTResult对象里,包括请求返回的状态:失败还 ...