关闭

为什么Java中的String是不可变的?

标签: java
558人阅读 评论(0) 收藏 举报
分类:

原文:Why String is immutable in Java ?
翻译:get-set


String是Java中的一个不可变类。所谓不可变,简单来说就是其对象不能被修改。实例中的所有信息在初始化的时候就已经具备,并且不能被修改(老外好啰嗦…)。不可变类有很多优点。这篇文章简要说明了为什么String被设计为不可变类。关于其好的回答应该建立在对内存模型、同步和数据结构等的理解之上。

1. 字符串池的需求

字符串池是一个位于方法区的特殊区域。当一个字符串被创建的时候,如果该字符串已经存在于字符串池中,那么直接返回该字符串的引用,而不是创建一个新的字符串。
下边的代码将只会创建一个字符串对象:

String s1 = "abcd";
String s2 = "abcd";

就不上图了,这块的内容前一篇翻译的文章已经解释过了。也就是s1s2都指向同一个字符串对象。
如果String不是不可变的,那么修改s1的字符串对象同样也会导致s2的内容发生变化。

2. 缓存Hashcode

字符串的hashcode在Java中经常被用到。例如,在一个HashMap中。其不可变性保证了hashcode(哈希值)总是保持不变,从而不用担心因hashcode变化导致的缓存问题。那就意味着,不用每次在其使用的时候计算其hashcode,从而更加高效。
String类中,有如下代码:

private int hash; //用来缓存hash code

3. 简化其他对象的使用

为了理解这一点,请看下边的代码:

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的设计(set包含不重复的元素)。当然这个例子是有问题的,在String类中是不存在value这个属性的。

4.安全性

字符串在许多的java类中都用作参数,例如网络连接,打开文件等等。如果字符串是可变的,一个连接或文件就会被修改从而导致严重的错误。可变的字符串也会导致在使用反射时导致严重的问题,因为参数是字符串形式的。
举例如下:

boolean connect(String s) {
    if (!isSecure(s)) {
        throw new SecurityException();
    }
    // 如果s内的值被修改,则会导致出现问题
    doSomethind(s);    
}

(虽然略牵强,但是也有一定道理)

5. 不可变的对象本身就是线程安全的

不可变的对象,可以在多个线程间自由共享。从而免除了进行同步的麻烦。

总之, String被设计为不可变的类,是出于性能和安全性的考虑,这也是其他所有不可变类应用的初衷。


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:131432次
    • 积分:1302
    • 等级:
    • 排名:千里之外
    • 原创:53篇
    • 转载:3篇
    • 译文:3篇
    • 评论:3条
    最新评论