• 走近Java之幕后的String


    前几天,有个同事问了我一个表面看起来显而易见的问题,是关于String的,我们一起来看一下(如果有说的不正确的地方,欢迎大家指正)。

    image

    java中,字面量在编译期计算,并且String字面量作为常量,存储在方法区中,仅保留一份。带有变量的计算,在运行期执行。那么,str3在执行的时候,发生了什么。

    第一步,初始化一个StringBuilder对象,并在构造器中调用父类AbstractStringBuilder的构造器,初始化一个长度16的字符数组

    image

    image

    第二步,调用StringBuilder的append()方法,传入变量str1,内部调用父类AbstractStringBuilder的append()方法

    image

    image

    在入参不为null的情况下,先调用ensureCapacityInternal()方法,判断拼接后的字符串长度是否超过当前字符数组的长度。如果超过了,就计算一个新的长度,然后创建一个新的数组,将现有数组的值复制给它,

    image

    具体扩容规则是,将当前字符数组长度扩容一倍再加2,如果扩容后的数组长度还不够,就和Integer.MAX_VALUE - 8(即MAX_ARRAY_SIZE)比较,如果还不够,则就用拼接后的字符串长度,但是最大也不能超过Integer.MAX_VALUE。(有一个newCapacity <= 0的判断,是考虑到value.length << 1变负数;至于扩容一倍还要+2,个人以为是为了提高性能,普遍计算得出,如果有不同理解,欢迎大家评论)

    image

    image

    第三步,调用str.getChars()方法,将入参字符串拼接到现有的字符数组后面,实际操作是调用本地方法

    System.arraycopy()。
    image

    第四步,记录下字符个数,最后返回当前StringBuilder对象。

    第五步,拼接字符串”bbb”,重复第二步到第四步,

    最后,调用StringBuilder的toString方法,去掉多余的空字符,返回一个当前累计字符长度的String对象,

    其实也是调用本地方法System.arraycopy()。复制一个新的字符数组。正好符合String的不变类特性。

    image

    image

    image

    作者:wangl110
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    var 全局变量 局部变量
    C#的发展历程第五
    优雅的处理Redis访问超时
    《集体智慧编程》读书笔记10
    《集体智慧编程》读书笔记9
    C#码农的大数据之路
    C#码农的大数据之路
    C#码农的大数据之路
    C#码农的大数据之路
    .NET遇上Docker
  • 原文地址:https://www.cnblogs.com/wangl110/p/10721018.html
Copyright © 2020-2023  润新知