String为何不可变?

前言

Java中的String是不可变的,这是程序员普遍都知道的,但是很多蛋疼的面试官都喜欢问为什么String要被设计成不可变的,这样有什么好处等等...本章就简单讲述一下该题。

Final的不可变

String创建好后真的不可变吗? 相信很多人都听过这个疑问,有人小伙伴说通过反射可以修改String,如下:

public static void main(String[] args) throws Exception{
    String text = "Hello";
    Field field = String.class.getDeclaredField("value");
    field.setAccessible(true);
    char[] value = (char[]) field.get(text);
    value[0] = 's';
    System.out.println(text);//sello
    System.out.println(text == "Hello"); //true
}

大家可以运行这个案例看一下,看看其中有什么问题。这里我们通过反射将text的值Hello修改为了sello,然后我们声明了一个Hello字符串与之引用比较,它们结果居然相等?

String底层其实是一个char数组,并且这个数组是被final所修饰,那这个不可变,指的是什么呢?这里需要特意说明一下: 被final所修饰的变量,不可变的是它的引用,而不是它的值。表示这个属性的引用,无法重新指向一个对象。

上边这个案例其实就是修改了char数组中索引为0的元素的值,其实本质上该String还是不可变的。

String不可变的好处

  1. 安全性
    String是Java中最基础也是使用最频繁的类型之一,而不可变类型的好处就是安全,它能避免很多关于安全性的问题。

  2. 缓存
    Java中的每一个String都会缓存到字符串常量池中,以此达到复用效果, 节省内存空间,如果String是可变的,我们在某一处修改了String那么所有引用该常量的地方将会全部跟随修改。这可能就直接违背了字符串常量池存在的意义。

  3. 线程安全
    String的所有方法都不会修改原有对象,它都会创建一个新的String,所有的进一步操作都会在新的String上,所以在多线程环境下也是可以直接使用的。

  4. 性能
    String作为Map容器的最爱,其很大原因就是因为String是不可变的,我们都知道HashMap的key是要使用对象的hashCode()方法来进行取模,而Stringhashcode只会计算一次,因为他是不可变的,计算一次后就会缓存起来。也就是说Stringhashcode也是不可变的,这就能很好的满足Map的key要求。

posted @ 2022-05-23 17:07  Zero9501  阅读(55)  评论(0编辑  收藏  举报