请选择 进入手机版 | 继续访问电脑版
本站特色:极好的技术研究氛围!所有技术交流,必有回复!

疯狂Java联盟

 找回密码
 加入联盟
查看: 253|回复: 0

Java字符串(String)的一个编译优化坑

[复制链接]
发表于 2018-4-16 00:15:39 | 显示全部楼层 |阅读模式
先来看下面一段代码:
  • String s = "a";
  • s = s + "b";
  • s = s + "c";



上面这段代码,虽然简单,但是其性能非常差。
很多人都觉得,上面的代码会有所谓的“编译器”优化,优化之后的代码应该像下面的:
  • StringBuilder builder = new StringBuilder();
  • builder.append("a");
  • builder.append("b");
  • builder.append("c");



但实际上不是!我们来看编译后的结果:

  • 0: ldc           #2                  // 创建字符串a
  • 2: astore_1
  • 3: new           #3                  // 创建StringBuilder对象
  • 6: dup
  • 7: invokespecial #4                  // 调用StringBuilder的构造器
  • 10: aload_1
  • 11: invokevirtual #5                  // 把a添加到StringBuilder里面
  • 14: ldc           #6                  // 创建字符串b
  • 16: invokevirtual #5                  // 把字符串b添加到StringBuilder里面
  • 19: invokevirtual #7                  // 把StringBuilder转换为String,赋予给变量s
  • 22: astore_1
  • 23: new           #3                  // 又创建StringBuilder对象
  • 26: dup
  • 27: invokespecial #4                  // 又调用StringBuilder的构造器
  • 30: aload_1
  • 31: invokevirtual #5                  // 又把ab添加到StringBuilder里面
  • 34: ldc           #8                  // 又创建字符串c
  • 36: invokevirtual #5                  // 又把c添加到StringBuilder里面
  • 39: invokevirtual #7                  // 又toString



也就是实际代码类似下面:
  • String s = "a";
  • s = new StringBuilder().append(s).append( new String("b") ).toString();
  • s = new StringBuilder().append(s).append( new String("c") ).toString();


// 实际上append方法的时候不需要new String,这里只是为了说明创建对象。

基于上面的理由,都表明了一个现象:String的+操作性能特别差。

那么问题来了,编译优化到底有没有用的呢?其实还是有用的,最典型的就是常量的优化:
  • final String s = "a";
  • final String s2 = s + "b";
  • final String s3 = s2 + "c";
  • System.out.println( s3 );



实际优化后的代码如下:
  • 0: getstatic     #2                  // System.out
  • 3: ldc           #3                  // 声明字符串,内容abc
  • 5: invokevirtual #4                  // 调用println方法打印



由此可见,变量s、s2、s3都不存在,直接在使用s3变量的地方,有个常量abc,实际优化后的代码相当于:
  • System.out.println( "abc" );



结论:
1.非final的变量尽量自己使用StringBuilder进行拼接,避免String的+操作。
2.final的变量进行+操作的时候,实际上就是只有一个最终结果。那么直接使用字符串直接量(标量)进行+操作也是一样道理的。

您需要登录后才可以回帖 登录 | 加入联盟

本版积分规则

小黑屋|手机版|Archiver|疯狂Java联盟 ( 粤ICP备11094030号 )

GMT+8, 2018-12-13 02:30 , Processed in 0.257808 second(s), 6 queries , File On.

快速回复 返回顶部 返回列表