字符串为什么不可变?

String可能是Java中使用频率最高的引用类型,因此String类的设计者是精心打磨。

比如String的不可变。

String被final关键字修饰,所以不可以有子类,就意味着没有子类可以重写它的方法,改变它的行为。

String 类的数据存储在 char[] 数组中,而这个数组也被 final 关键字修饰了,这就表示 String 对象是没法被修改的,只要初始化一次,值就确定了。

这里是char,说明是旧版本(9)

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];
}

第一,可以保证String对象的安全性,避免被篡改,毕竟像密码这样的隐私信息就是使用字符串存储的。

第二,保证哈希值不会频繁变更,因为String要经常作为哈希表的键值,经常变更的话,哈希表的性能就会很差劲。

在String类中,哈希值是在第一次计算时缓存的,后续对该哈希值的请求将直接使用哦缓存值。这将有助于提高哈希表等数据结构的性能。

第三,可以实现字符串常量池,Java会将相同内容的字符串存储在字符串常量池中。这样,具有相同内容的字符串变量可以指向同一个String对象,节省内存空间。

由于字符串的不可变性,String类的一些方法实现最终都返回了新的字符串对象。

就拿substring来说

    public String substring(int beginIndex, int endIndex) {
        int length = length();
        checkBoundsBeginEnd(beginIndex, endIndex, length);
        if (beginIndex == 0 && endIndex == length) {
            return this;
        }
        int subLen = endIndex - beginIndex;
        return isLatin1() ? StringLatin1.newString(value, beginIndex, subLen)
                          : StringUTF16.newString(value, beginIndex, subLen);
    }

substring()方法用于截取字符串,最终返回的都是new出来的新字符串对象。

还有concat()方法

    public String concat(String str) {
        if (str.isEmpty()) {
            return this;
        }
        return StringConcatHelper.simpleConcat(this, str);
    }

    @ForceInline
    static String simpleConcat(Object first, Object second) {
        String s1 = stringOf(first);
        String s2 = stringOf(second);
        if (s1.isEmpty()) {
            // newly created string required, see JLS 15.18.1
            return new String(s2);
        }
        if (s2.isEmpty()) {
            // newly created string required, see JLS 15.18.1
            return new String(s1);
        }
        // start "mixing" in length and coder or arguments, order is not
        // important
        long indexCoder = mix(initialCoder(), s1);
        indexCoder = mix(indexCoder, s2);
        byte[] buf = newArray(indexCoder);
        // prepend each argument in reverse order, since we prepending
        // from the end of the byte array
        indexCoder = prepend(indexCoder, buf, s2);
        indexCoder = prepend(indexCoder, buf, s1);
        return newString(buf, indexCoder);
    }

concat()方法用于拼接字符串,不管编码是否一致,最终也返回的是新的字符串对象。

replace()替换方法其实也一样,这就意味着,不管是截取、拼接、还是替换,都不是在原有的字符串上进行的,而是重新生成了新的字符串对象,也就是说,这些操作过后,原来的字符串对象并没有发生改变。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值