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 次创建和
销毁对象的时间。
String的'+'的性能及原理的更多相关文章
- warning:deprecated conversion from string constant to 'char *'
warning:deprecated conversion from string constant to 'char *' 解决方式 #include <iostream> using ...
- 也谈string.Join和StringBuilder的性能比较
前几天在园子里面看到一篇讲StringBuilder性能的文章.文章里面给出了一个测试用例,比较StringBuilder.AppendJoin和String.Join的性能.根据该测试结果,&quo ...
- Junit 注解 类加载器 .动态代理 jdbc 连接池 DButils 事务 Arraylist Linklist hashset 异常 哈希表的数据结构,存储过程 Map Object String Stringbufere File类 文件过滤器_原理分析 flush方法和close方法 序列号冲突问题
Junit 注解 3).其它注意事项: 1).@Test运行的方法,不能有形参: 2).@Test运行的方法,不能有返回值: 3).@Test运行的方法,不能是静态方法: 4).在一个类中,可以同时定 ...
- List<T>与Dictionary<string,T>频繁检索的性能差距
一直对LINQ简洁高效的语法青睐有加,对于经常和资料库,SQL语法打交道的C#开发者来说,LINQ无疑是一个非常不错的选择,当要在List<T>(T为一个普通对象)集合中查找满足某些条件的 ...
- .Net 中的 string、String、StringBuffer 内存处理性能 和 应用场景
body { font-family: Segoe UI, SegoeUI, Helvetica Neue, Helvetica, Arial, sans-serif } code { color: ...
- 【原创】Java和C#下String类型中的==和equals的原理与区别
一.Java下 1.几个例子 public static void main(String[] arge) { String str1 = new String("1234"); ...
- react+redux渲染性能优化原理
大家都知道,react的一个痛点就是非父子关系的组件之间的通信,其官方文档对此也并不避讳: For communication between two components that don't ha ...
- C风格字符串和C++ string 对象赋值操作的性能比较
<<C++ Primer>> 第四版 Exercise Section 4.3.1 部分Exercise 4.2.9 习题如下: 在自己本机执行如下程序,记录程序执行时间: # ...
- React + Reflux 渲染性能优化原理
作者:ManfredHu 链接:http://www.manfredhu.com/2016/11/08/23-reactRenderingPrinciple 声明:版权所有,转载请保留本段信息,否则请 ...
随机推荐
- Elasticsearch--扩展索引结构
目录 索引树形数据 索引非扁平数据 索引关系型数据 使用嵌套对象 评分与嵌套查询 使用主从关系 索引树形数据 使用path_analyzer分析树形数据字段 索引非扁平数据 数据如下: { " ...
- Python学习笔记之默认参数
函数定义时 参数定义的顺序必须是:必选参数.默认参数.可变参数和关键字参数. def test(a,b,c=1,*d,**e) pass
- oracle插入字符串数据时,字符串中有'单引号
使用insert into(field1,field2...) values('val1','val2'...)时,若值中有单引号时会报错. 处理方法:判断一下val1,val2中是否含有单引号,若含 ...
- Windows开源Web服务器性能和压力测试工具
linux有很多开源工具用来测试服务器负载,而windows上非常少,几乎没有除了几个复杂的JMeter WET等 将两个好用的工具是Linux版本通过Cygwin移植过来,方便广大windows人员 ...
- arx 移动界面到一点
AcDbViewTableRecord view; AcGePoint3d max = acdbHostApplicationServices()->workingDatabase()-> ...
- CAD由一个自定义实体事件中的id得到自定义实体对象(com接口VB语言)
由一个自定义实体事件中的id得到自定义实体对象.该函数只能在自定义实体事件中调用. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 2 ...
- 梦想CAD控件安卓界面控制
CAD控件界面上所有元素都可以控制显示或隐藏,下面将逐一介绍详细用法. 设置工具文件 MxFunction.setToolFile 设置工具文件.详细说明如下: 参数 说明 String sFile ...
- ThinkPHP---thinkphp文件加载
[一]文件加载在ThinkPHP里提供了三种方式 实际开发里,文件加载方式一般以第一种为主(通过函数库形式自动加载,此时我们仅仅需要定义文件和函数) (1)函数库形式加载 函数库分3种级别,系统函数库 ...
- 17Oracle Database 维护
Oracle Database 维护 备份 还原
- docker 转载
写的非常好的一篇文章,不知道为什么被删除了. 利用Google快照,做个存档. 快照地址:地址 作者地址:青牛 什么是docker Docker 是一个开源项目,诞生于 2013 年初,最初是 do ...