为何Java中的String是不可变的

原文出处:https://www.programcreek.com/2013/04/why-string-is-immutable-in-java/ java

JavaString类是不可变的,简单来讲,一个不可变的类就意味着他的实例是不可修改的,实例的全部信息都是在实例建立的时候被初始化而且不可被修改。不可变类的设计有不少优势。这篇博文主要从内存,同步和数据结构的角度来具体说明这种不可变的概念。 缓存

String Pool的须要

String PoolString intern pool)是在方法区的一块特殊存储区域。当一个String被建立时若是发现当前String已经存在于String Pool,则会返回一个已存在String的引用而不会新建一个对象。安全

如下代码只会建立一个String对象在堆内存中。网络

String string1 = "abcd";
String string2 = "abcd";

  下图是建立的过程:数据结构

image.png

若是一个String是可变的,改变了一个引用指向的String会致使其余引用获得错误的值。多线程

缓存Hashcode

Java中,对于StringHashcode使用是很是频繁的,例如在HashMapHashSet中。将String设计成不可变能够保证他的Hashcode始终一致,这样Hashcode就能够被缓存而且不用担忧变化。这就意味着,不须要在每次使用String的时候都去计算他的Hashcode,这也使得程序运行的更加高效。ide

 

String类中,关于Hashcode的代码以下this

private int hash;//this is used to cache hash code.

简化其余对象的使用

为了更加详细的阐述,咱们考虑如下程序:spa

HashSet<String> set = new HashSet<String>();
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类中没有value这个字段。线程

安全

String在不少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);
}

不可变对象天生线程安全

由于不可变对象不能被改变,他们能够在多线程中被自由的共享,这就消除了对象同步的需求。

总的来讲,String被设计成不可变的出发点是效率和安全。这也是不可变类在不少状况下被优先使用的缘由。

相关文章
相关标签/搜索