逛了几个论坛。

不少人在讨论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的&#39;+&#39;的性能及原理的更多相关文章

  1. warning:deprecated conversion from string constant to &#39;char *&#39;

    warning:deprecated conversion from string constant to 'char *' 解决方式 #include <iostream> using ...

  2. 也谈string.Join和StringBuilder的性能比较

    前几天在园子里面看到一篇讲StringBuilder性能的文章.文章里面给出了一个测试用例,比较StringBuilder.AppendJoin和String.Join的性能.根据该测试结果,&quo ...

  3. Junit 注解 类加载器 .动态代理 jdbc 连接池 DButils 事务 Arraylist Linklist hashset 异常 哈希表的数据结构,存储过程 Map Object String Stringbufere File类 文件过滤器_原理分析 flush方法和close方法 序列号冲突问题

    Junit 注解 3).其它注意事项: 1).@Test运行的方法,不能有形参: 2).@Test运行的方法,不能有返回值: 3).@Test运行的方法,不能是静态方法: 4).在一个类中,可以同时定 ...

  4. List<T>与Dictionary<string,T>频繁检索的性能差距

    一直对LINQ简洁高效的语法青睐有加,对于经常和资料库,SQL语法打交道的C#开发者来说,LINQ无疑是一个非常不错的选择,当要在List<T>(T为一个普通对象)集合中查找满足某些条件的 ...

  5. .Net 中的 string、String、StringBuffer 内存处理性能 和 应用场景

    body { font-family: Segoe UI, SegoeUI, Helvetica Neue, Helvetica, Arial, sans-serif } code { color: ...

  6. 【原创】Java和C#下String类型中的==和equals的原理与区别

    一.Java下 1.几个例子 public static void main(String[] arge) { String str1 = new String("1234"); ...

  7. react+redux渲染性能优化原理

    大家都知道,react的一个痛点就是非父子关系的组件之间的通信,其官方文档对此也并不避讳: For communication between two components that don't ha ...

  8. C风格字符串和C++ string 对象赋值操作的性能比较

    <<C++ Primer>> 第四版 Exercise Section 4.3.1 部分Exercise 4.2.9 习题如下: 在自己本机执行如下程序,记录程序执行时间: # ...

  9. React + Reflux 渲染性能优化原理

    作者:ManfredHu 链接:http://www.manfredhu.com/2016/11/08/23-reactRenderingPrinciple 声明:版权所有,转载请保留本段信息,否则请 ...

随机推荐

  1. Asp.net MVC中文件上传的参数转对象的方法

    参照博友的.NET WebApi上传文件接口(带其他参数)实现文件上传并带参数,当需要多个参数时,不想每次都通过HttpContext.Request.Params去取值,就针对HttpRequest ...

  2. 关于百度地图导航AndroidSDK的初始化问题

    使用百度地图有一段时间了,导航是一个一直困扰我的问题.今天刚发现百度地图的导航SDK并不是对Android6.0版本不兼容.而是对某一部分手机不兼容,准确的说是对X64或X86的cpu不兼容.下载百度 ...

  3. CNN结构:可用于时序预测复合的DNN结构-AcGANs、误差编码网络 ENN

    前言:模式识别问题 模式函数是一个从问题定义域到模式值域的一个单射. 从简单的贝叶斯方法,到只能支持二分类的原始支持向量机,到十几个类的分类上最好用的随机森林方法,到可以支持ImageNet上海量18 ...

  4. 【sqli-labs】 对于less34 less36的宽字节注入的一点深入

    1.AddSlashes() 首先来观察一下是如何通过构造吃掉转义字符的 先将less 34的网页编码换成gbk 加上一些输出 echo "Before addslashes(): &quo ...

  5. @ExceptionHandler和@ControllerAdvice统一处理异常

    //@ExceptionHandler和@ControllerAdvice统一处理异常//统一处理异常的controller需要放在和普通controller同级的包下,或者在ComponentSca ...

  6. JAVA基础——Native关键字

    一:native声明 在Java中native是关键字.它一般在本地声明,异地用C和C++来实现.它的声明有几点要注意: 1)native与访问控制符前后的关系不受限制. 2)必须在返回类型之前. 3 ...

  7. 牛客练习赛25 C 再编号

    解题思路 我们先来观察一下题目中给出的公式 $$a'_i=(\sum_{j=1}^na_j)-a_i$$ 通过这个公式推一下经过再编号后的序列的总和,因为我们推出这个和之后可以进行下一次计算. $$\ ...

  8. Boundary Conditions

    test test Table of Contents 1. Boundary conditions 1.1. Neumann boudary condition vs Dirichlet BC 1. ...

  9. 【Codeforces 923A】Primal Sport

    [链接] 我是链接,点我呀:) [题意] 题意 [题解] 考虑怎么得到数字x2=N,假设是质数p的倍数 那么x1肯定在x2-p+1~x2这个范围内才行 因为p的倍数要刚好大于等于x1, 所以x1肯定是 ...

  10. App后台开发运维和架构实践学习总结(5)——App产品从需求到研发到开发到上线到产品迭代全过程

    前言 如果没有做过开发,研发过产品的人,很难体会做产品的艰难,刚进公司的人,一般充当的是程序开发,我这里说的是开发,它与研发是有区别的. 一个需求下来,如果不能很好地理解产品需求,如果不能很好的驾驭需 ...