曾经,在学习的途中,我时常感到疑惑,那就是String的不可变。
首先,什么是不可变呢,例子如下:
public class ImmutableExample {
public static void main(String[] args) {
String str1 = "Hello";
String str2 = str1.concat(" World");
System.out.println(str1); // 输出:Hello
System.out.println(str2); // 输出:Hello World
}
}
在这个例子中,str1 的值始终是 “Hello”,即使调用了 concat 方法,也不会改变 str1,而是返回了一个新的字符串 str2。
那么,我有了疑问,它为什么是不可变的呢?为什么要有这样一个不可变的类在Java中存在呢,它存在的目的是什么?
答案是:String 类使用 final
修饰是因为 Java 设计者希望 String对象具有不可变性(immutability)。将 String 类声明为 final
,可以确保其不可被继承,从而实现它的不可变性,进而带来了安全性、性能和多线程环境下的优点。
不可变性(Immutability)
String
对象一旦创建,就不能更改其内容。不可变性意味着字符串的内容在创建后是固定的,不会被改变。这样设计的原因包括:
- 安全性:不可变的
String
对象在系统中被广泛使用,如文件路径、网络连接等。因为不可变性,它们不会被修改,可以安全地作为==关键值(如哈希表的键)==使用。 - 线程安全:
String
的不可变性使得它在多线程环境下是安全的,不会出现线程修改字符串值的问题。
哈希缓存
String
类通常用作哈希表的键。为了优化性能,String
的 hashCode
值会在创建时计算并缓存,以便后续使用。因此,String
的不可变性保证了 hashCode
的值不会改变,否则可能导致哈希值变化,出现哈希表查找失败的情况。
安全性(Security)
在许多安全操作中,String
类经常用于存储敏感信息,如用户名、密码、网络地址等。若字符串可变,可能导致这些信息在执行过程中被恶意修改,带来安全隐患。不可变的 String
能确保这些数据的完整性和安全性。
字符串池(String Pool)优化
Java 采用字符串池技术来优化内存使用,当创建一个字符串时,会首先检查字符串池中是否已存在该字符串,如果存在则复用已有的字符串实例,不会再创建新的对象。由于字符串是不可变的,多个引用可以安全地指向同一个字符串实例,从而减少内存开销。
禁止继承(final 类的设计目的)
如果 String
不是 final
类,那么它可以被继承,而子类可能会改变其不可变性,这样就破坏了 String
不可变的设计初衷。因此,final
修饰可以防止其他类修改 String
的行为。
总结来说,String
类使用 final
修饰确保了它的不可变性、线程安全性和内存使用效率,使其在 Java 应用中更加安全和高效。