Java为什么吧String设计为不可变类?
Posted 杨 戬
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java为什么吧String设计为不可变类?相关的知识,希望对你有一定的参考价值。
文章目录
在Java中String类由final修饰,所以不能被继承。被final修饰主要是为了让String成为一个不可变类
因为要保证String类的不可变,那么将这个类定义为final 的就很容易理解了。如果没有 final 修饰,那么就会存在String的子类,这些子类可以重写String类的方法,强行改变字符串的值,这便违背了String类设计的初衷。
那么为什么要这么设计呢?
在Java中,String类被设计为不可变类,主要表现在它保存字符串的成员变量是final的。
-
Java 9之前字符串采用char[]数组来保存字符,即
private final char[] value ;
-
Java 9做了改进,采用byte[]数组来保存字符,即
private final byte[] value ;
之所以要把String类设计为不可变类,主要是出于安全和性能的考虑,可归纳为如下4点。
防止被篡改,保证信息数据的安全性
由于字符串无论在任何 Java 系统中都广泛使用,会用来存储敏感信息,如账号,密码,网络路径,文件处理等场景里,保证字符串 String 类的安全性就尤为重要了,如果字符串是可变的,容易被篡改,那我们就无法保证使用字符串进行操作时,它是安全的,很有可能出现 SQL 注入,访问危险文件等操作。
不变的对象和值是线程安全的
在多线程中,只有不变的对象和值是线程安全的,可以在多个线程中共享数据。由于 String 天然的不可变,当一个线程”修改“了字符串的值,只会产生一个新的字符串对象,不会对其他线程的访问产生副作用,访问的都是同样的字符串数据,不需要任何同步操作。
哈希值的唯一性来挺好性能
字符串作为基础的数据结构,大量地应用在一些集合容器之中,尤其是一些散列集合,在散列集合中,存放元素都要根据对象的 hashCode() 方法来确定元素的位置。由于字符串 hashcode 属性不会变更,保证了唯一性,使得类似 HashMap,HashSet 等容器才能实现相应的缓存功能。由于String 的不可变,避免重复计算 hashcode ,只要使用缓存的 hashcode 即可,这样一来大大提高了在散列集合中使用 String 对象的性能。
提高常量池的可用性
当字符串不可变时,字符串常量池才有意义。字符串常量池的出现,可以减少创建相同字面量的字符串,让不同的引用指向池中同一个字符串,为运行时节约很多的堆内存。若字符串可变,字符串常量池失去意义,基于常量池的 String.intern()
方法也失效,每次创建新的字符串将在堆内开辟出新的空间,占据更多的内存。
以上是关于Java为什么吧String设计为不可变类?的主要内容,如果未能解决你的问题,请参考以下文章
在Java中String类为什么要设计成final?String真的不可变吗?其他基本类型的包装类也是不可变的吗?
为什么 Java 中的 String 是不可变的(Immutable)?