5分钟理解String的'+'的性能及原理

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."":()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 次创建和销毁对象的时间。

原文发布于微信公众号 - 好好学java(SIHAIloveJAVA)

原文发表时间:2018-11-01

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏简书专栏

Python正则表达式re库的使用

re.search函数需要传入2个参数,第1个参数是正则表达式,第2个参数是要进行搜索的源字符串。 re.search函数返回结果的数据类型是sre.SRE_...

19320
来自专栏PHP实战技术

你应该这个姿势学习PHP(2)

2、is_array(),is_bool,is_int(),is_integer(),is_numeric(),is_string(),is_object(),...

40960
来自专栏CSDN技术头条

常见的七种排序算法解析

01 选择排序 实现原理 首先从未排序序列中找到最小的元素,放置到排序序列的起始位置,然后从剩余的未排序序列中继续寻找最小元素,放置到已排序序列的末尾。所以称之...

21080
来自专栏尾尾部落

[剑指offer] 数组中重复的数字

在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复...

10530
来自专栏猿人谷

static_cast ,reinterpret_cast

用法:static_cast < type-id > ( expression ) 该运算符把expression转换为type-id类型,但没有运行时类型检查...

236100
来自专栏Python小屋

Python内置函数sorted()和列表方法sort()排序规则不得不说的事

Python内置函数sorted()和列表方法sort()可以使用key参数指定排序规则,并且都是稳定排序,也就是说,对于指定规则不能涵盖的元素,本来谁在前面,...

27630
来自专栏柠檬先生

Python 基础 高阶函数

python 把函数作为参数   如果传入abs 作为参数     def add(x,y,y):       return f(x) + f(y)     a...

31590
来自专栏北京马哥教育

Python数据类型知识点全解

作者:zhang_derek 1.字符串 字符串常用功能 name = 'derek' print(name.capitalize()) #首字母大写 ...

30650
来自专栏前端知识分享

第203天:js---Array对象常用方法

9620
来自专栏Python入门

Python函数式编程-高阶函数、匿名函数、装饰器、偏函数

本篇文章我们来介绍下Python函数式编程的知识。最主要的一点,Python中的函数是对象,可以复制给变量!好了,我们来介绍几个Python函数式编程中的要点,...

12820

扫码关注云+社区

领取腾讯云代金券