String的'+'的性能及原理
逛了几个论坛。
不少人在讨论String的“+”,StringBuilder与StringBuffer等一系列的问题。先不多说了了
现分类详述:
1、String的‘+’,底层运行。及效率问题
2、StringBilder与StringBuffer的比較
本篇博文先介绍第一个问题
为了让大家看明确,
我们举例说明吧!
为了加深理解,我们能够来做几个小实验。
javac Test 编译文件
javap -c Test 查看虚拟机指令
实验一:纯字符串
public class Test { public static void main(String args[]) { String str = "a"; } }
// 将字符串 a 存入常数池
0: ldc #2; //String a
// 将引用存放到 1 号局部变量中
2: astore_1
3: return
实验二:纯字符串相加
public class Test { public static void main(String args[]) { String str = "a" + "b"; } }
// 将字符串 ab 压入常数池
0: ldc #2; //String ab
2: astore_1
3: return
实验二能够非常明显地看出,编译器在编译时产生的字节码已经将 "a" + "b" 优化成了 "ab",
同理多个字符串的相加也会被优化处理,须要注意的是字符串常量相加。
实验三:字符串与自己主动提升常量相加
public class Test { public static void main(String args[]) { String str = "a" + (1 + 2); } }// 将字符串 a3 压入常数池
0: ldc #2; //String a3
2: astore_1
3: return
通过虚拟机指令能够看出,1 + 2 自己主动提升后的常量与字符串常量,虚拟机也会对其进行优化。
实验二、实验三结论:常量间的相加并不会引起效率问题
实验四:字符串与变量相加
public class Test { public static void main(String args[]) { String s = "b"; String str = "a" + s; } }// 将字符串 b 压入常数池
0: ldc #2; //String b
// 将引用存放到 1 号局部变量中
2: astore_1
// 检查到很量的相加。这时创建 StringBuilder 对象
3: new #3; //class java/lang/StringBuilder
// 从栈中复制出数据。即把字符串 b 复制出来
6: dup
// 调用 StringBuilder 的初始构造
7: invokespecial #4; //Method java/lang/StringBuilder."<init>":()V
// 将字符串 a 压入常数池
10: ldc #5; //String a
// 调用 StringBuilder 的 append 方法,把字符串 a 加入进去
12: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
// 从 1 号局部变量中载入数据引用
15: aload_1
// 调用 StringBuilder 的 append 方法,把字符串 b 加入进去
16: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
// 调用 StringBuilder 的 toString 方法
19: invokevirtual #7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
// 将 toString 的结果保存至 2 号局部变量
22: astore_2
23: return
实验四能够看出,很量字会串相加时,因为相加的变量中存放的是字符串的地址引用。
由于在编译时无法确切地知道其它详细的值,也就没有办法对其进行优化处理,这时为了
达到连接的效果,其内部採用了 StringBuilder 的机制进行处理(JDK 5 中新增的,我
这里没有 JDK 1.4,预计在 JDK 1.4 下採用的是 StringBuffer),将他们都 append
进去,最后用 toString 输出。
若 s 为其它类型时,比方:int 类型,也是採用同种方式进行处理。
同理。依据实验二的结果,在 String str = "a" + "b" + s; 时。先会优化成 "ab" 再与
s 依据实验四的方式进行处理。这时 StringBuilder 仅调用了两次 append 方法。
假设是 String str = "a" + s + "b"; 这样的形式的就没办法优化了。StringBuilder 得调
用三次 append 方法。
实验四的结论表明,字符串与变量相加时在内部产生了 StringBuilder 对象并採取了一定
的操作。
假设仅仅有一句 String str = "a" + s; 这样子的,其效率与
String str = new StringBuilder().append("a").append(s).toString();
是一样的。
一般所说的 String 採用连接运算符(+)效率低下主要产生在下面的情况中:
public class Test { public static void main(String args[]) { String s = null; for(int i = 0; i < 100; i++) { s += "a"; } } }每做一次 + 就产生个 StringBuilder 对象,然后 append 后就扔掉。下次循环再到达时重
新产生个 StringBuilder 对象。然后 append 字符串,如此循环直至结束。
假设我们直接採用 StringBuilder 对象进行 append 的话,我们能够节省 N - 1 次创建和
销毁对象的时间。
相关文章
- POJ--2449--Remmarguts' Date【dijkstra_heap+A*】第K短路
- 对js运算符“||”和“&&”的总结
- 我的Android进阶之旅------>Android系统设置默认来电铃声、闹钟铃声、通知铃声
- <<Python基础教程>>学习笔记 | 第10章 | 充电时刻
- Javascript正则构造函数与正则表达字面量&&常用正则表达式
- 2014百度校招笔试题之动态链接库&静态链接库详解
- CSDN日报190826:卷积神经网络CNN(干货满满),架构设计指南:MVC、MVP & MVVM模式
- 大话游戏循环Game Loop——Python&C++
- # ? & 号在url中的的作用
- 【性能测试】Jmeter工具使用1-练习题&详细答案
- 2020上半年收集到的优质AI文章 – 开源框架&算法&数据集
- 《C++ AMP:用Visual C++加速大规模并行计算》——3.7 使用restrict(amp)标记的函数
- 《PHP、MySQL和Apache入门经典(第5版)》一2.10 Q&A
- apache kafka & CDH kafka源码编译
- CALayer & bitmap Content
- 淘宝内部分享:MySQL & MariaDB性能优化 【转】
- 30款基本UX工具 - 思维流程工具 & 原型工具
- Spring -- Bean自己主动装配&Bean之间关系&Bean的作用域
- How to improve Java's I/O performance( 提升 java i/o 性能)
- List<Map<String, String>> 开启 Map<String, List<String>>
- 学习笔记(33):Python网络编程&并发编程-进程池线程池