【Java小知识】String为什么不可变?改变你对String不可变的认知

String

String类是final类型的,所以使用String定义的字符串是一个常量,因此他一旦创建,其内容和长度是不可改变的。真的是这样简单的吗?

String不可变详解

定义字符串时,在String源码中实际是将字符串赋值给了一个char类型的数组。下面都称为字符数组。

   public String(String original) {
        this.value = original.value;
        this.hash = original.hash;
    }
/** The value is used for character storage. */
    private final char value[];

我自己之前以为String不可变是因为字符数组被final修饰。

其实不然,final修饰引用类型,它保存的仅仅是一个引用,final只保证这个引用类型变量所引用的地址不会改变,也就是一直引用同一个对象,但这个对象完全可以发生改变。

拿下面的例子来说,char类型的数组被final修饰,表示value不可指向新的数组,但是当前数组里面的值是可变的。
在这里插入图片描述

可以看出修改数组中的值是可以的,但是让当前变量指向新数组时会报错。
在这里插入图片描述

综上所述,String不能被改变最主要的是字符数组被private修饰。而且String也没有提供可以修改字符数组的api,外界不可访问value[],自然String就不能被修改。

为什么String要设计成不可变

当我们使字面量进行创建字符串时,会在常量池中查找是否有相同值的字符串,如果有则会返回其引用,否则会创建新的字符串,并返回新字符串的引用。
在这里插入图片描述
可以看到上述代码str和str1的地址是相同的。

在这里插入图片描述
在上述代码中,str的字符串值是“123”,当创建str1时,会从字符串常量池找到一开始创建的str,并返回引用给str1。因此str和str1的引用地址是相同的,如果字符串可变,我们给str重新赋值为“456”,那么str1也会变成456。

看一下打印结果在这里插入图片描述可以看到str1的值是没有变的,还是123。
如果str1的值会变的话,肯定会影响使用,假如在其他业务逻辑中使用了str1,是不是会造成很严重的后果呢。

所以字符串设计成不可变,可以保证数据的准确性。如果String可变的话,会导致别人在使用时,出现结果不一致的情况。字符串常量池本来就是提供字符串复用的,如果字符串可变,那么复用也就是无稽之谈了。


版权声明:本文为weixin_45342093原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。