美文网首页高级javaJava 杂谈程序员
图说String(三)String中'+'和St

图说String(三)String中'+'和St

作者: 微笑的小小刀 | 来源:发表于2018-10-16 14:00 被阅读8次

    上⽂文说到,对String的任何修改操作,都会返回⼀一个新的String对象,并且举例例 了了常⽤用的subString的⽅方法调⽤用,今天我们来看String另外⼀一个常⽤用的操作:+ 拼 接操作。 String s ="java"+"技术⼤大本营" ;这个好像看不不到源码,但是我们可以通过idea直接打开 .class ⽂文件看到 jvm 是怎 么编译这个java⽂文件的。如下图所示:


    1clipboard.png

    可以看到,在编译的时候,直接跳过了了 + 号,直接当做"java技术⼤大本营"来处理理 的。
    因为在做' '=='' 引⽤用时会输出true:


    2clipboard.png

    ⽤用 “==” ⽐比较时输出true,说明变量量 s 和 变量量 s1 的地址是⼀一样的。我们可以通 过javap命令看看常量量池: javap -v -p IS_String

    3clipboard.png

    可以看到, s和s1分别在本地变量量表的 Slot1 和 Slot2 区域。 在main函数反编译 代码中可以看到:


    4clipboard.png

    0:从常量量池#2中加载常量量到操作栈顶。2:将栈顶的数存储到本地变量量表1区域,也就是赋值给Slot1中的变量量s 3:从常量量池#2中加载常量量到操作栈顶。5:将栈顶的数存储到本地变量量表2区域,也就是赋值给Slot2中的变量量s1


    5clipboard.png
    6clipboard.png

    可以看到常量量池#2的位置就是我们的字符串串: “java技术⼤大本营”。 上述例例⼦子是⽤用 + 连接字符串串常量量,jvm会帮我们直接连接成⼀一个常量量。下⾯面我们 看看⽤用 “+” 连接变量量:


    7clipboard.png

    上半部分是源码,下半部分是⽤用javap -v -p IS_String 反编译出来的结果。 我们可以看到, "java" 和 "技术⼤大本营” 是分到常量量池两个位置进⾏行行存储的。在 使⽤用 + 进⾏行行连接时,使⽤用了了invokedynamic指定动态去调⽤用BootstrapMethods⾥里里编号为0的⽅方法:


    8clipboard.png

    我们在idea中打开这个源码⽂文件 (StringConcatFactory.makeConcatWithConstants)可以看到:


    9clipboard.png

    我们跟踪doStringConcat代码可以看到主要是generate⽅方法:


    10clipboard.png 11clipboard.png

    可以看到,对字符串串拼接,jvm做了了多种策略略,在划红线处可以看到,上⾯面5种是 基于StringBuilder做字符拼接。 最后⼀一个,如果是内联的拼接,则是基于InlineCopy做的字符串串拼接,⼜又回到了了我们上⽂文的总结,对String的操作都是对其内部的 byte数组操作。有兴趣的⼩小伙伴可以继续跟踪下去看看实现细节。

    总结:如果⽤用 + 直接拼接常量量,则jvm会在编译时就连接好当做⼀一个常量量处理理。 如果是⽤用 + 拼接变量量,则会根据拼接的⽅方式,选择不不同的拼接⽅方式,不不⼀一定是StringBuilder的append哦

    欢迎大家关注公众号:java技术大本营, 质量内容号,专心写好每一篇技术文。欢迎留言一起讨论

    qrcode_for_gh_cb04da16e26d_258.jpg

    相关文章

      网友评论

        本文标题:图说String(三)String中'+'和St

        本文链接:https://www.haomeiwen.com/subject/brzczftx.html