在Java中string是不变的类,一个不变的类是不可以修改类的实例的。当一个实例被创建,所有信息都被初始化在这个实例中,并且都不能修改。不变的类有很多优点,这篇文章总结了为什么string被设计为不变的类。一个很好的回答要需要我们深入的理解内存,同步,数据结构等。
1.string池请求
string池是特别的存储在Method area中,当一个string被创建或者这个string已经存在池中,这个string的引用将会返回,而不是创建一个新的对象并且返回这个引用。
下列的代码仅创建一个对象在堆中。
String string1 = "abcd";
String string2 = "abcd";
我们看下面的图解
如果string是可变的,改变这个string的引用将导致这个新的引用指向错误的值。
2.Hashcode 缓存
在Java中string 的hashcode频繁的使用,例如,在HashMap中,不可变的string可以保证哈希值总是相同的,以致可以不用担心会被改变。这意味着,每次使用时都不需要计算哈希代码,这将更有效率。
在string类中,有以下代码
private int hash;//this is used to cache hash code.
3.使用其他对象很方便
考虑下面的代码
HashSet set = new HashSet();
set.add(new String("a"));
set.add(new String("b"));
set.add(new String("c"));
for(String a: set)
a.value = "a";
在这个例子中,如果string可以变,这里的值将会被改变这将违反set的设计(在set中不能包含有重复的元素)。在这个例子设计简单的缘故,在string类中没有值域。
4.安全性
在很多的Java类中string作为参数很广泛的使用。比如,网络连接,打开文件等。就是因为string是不可以变的,连接或者打开文件会变改变,将导致严重的安全威胁。如果一个方法想连接一台机器,当如果可变就不能连接了。可变的string在反射作为一个参数可以造成严重的问题。
看下面的代码
boolean connect(string s){
if (!isSecure(s)) {
throw new SecurityException();
}
//here will cause problem, if s is changed before this by using other references.
causeProblem(s);
}
5.不可变的对象线程安全。
因为不可变的对象不能改变,它们可以多个线程自由的共享。这消除了做同步的要求。
总的来说,string被设计为不可变的缘故是效率和安全性,这也是为什么不可变的类的首选。