为什么String是不可变的

来源:互联网 发布:system halted linux 编辑:程序博客网 时间:2024/04/30 13:29

String是Java中的不可变类。不可变类即其对象是不修改的,对象一旦建立,就不可改变。不可变类有许多优点,下面简要介绍一下String为什么是不可变类,对内存、同步、数据结构的认识会有助于理解。

1.String常量池的需要

常量池(String intern pool)是方法区(method area)中的一个特殊区域。当一个String被创建时,如果该字符串在常量池中已存在,那么将会返回该字符串对象的引用,而不是重新创建一个新String对象并返回其引用。

下面的代码只会在堆中创建一个对象:

String string1="abcd";

<span style="white-space:pre"></span>String string2="abcd";
用一张图来说明:

java-string-pool

如果String是可变的,那么其中一个引用改变了字符串的值,将会导致另一个对该字符串的引用出错。

2.保存哈希码的需要

字符串的哈希码在Java中经常用到,如HashMap。不可变保证了哈希码永远是相同的,不必担心保存哈希码的改变。这样,就不必每次使用时都计算字符串的hashcode,保证了效率。

在String类里,有如下的代码:

<span style="white-space:pre"></span>private int hash;//this is used to cache hash code
3.使其他对象的使用更加容易

为了更具体地说明,请看下面的代码:

HashSet<String> set = new HashSet<String>();

<span style="white-space:pre"></span>set.add(new String("a"));<span style="white-space:pre"></span>set.add(new String("b"));<span style="white-space:pre"></span>set.add(new String("c")); <span style="white-space:pre"></span>for(String a: set)<span style="white-space:pre"></span>a.value = "a";
在这个例子中,如果String是可变的,其值的改变就会引起set设计的冲突(set用来存储不重复的元素)。这个例子只是用来简单的说明,在真实的String类里没有value域。

4.安全性

String在许多java内置类里作为参数被广泛应用,如network connection,open files等等。如果String是可变的,将导致连接或文件面临严重的安全威胁。方法可能会将某个连接误认为是对某台机器的连接,但实际上可能是另一台机器的。同时,可变类也会影响反射的安全性。

下面是一个例子:

<span style="white-space:pre"></span>boolean connect(string s){    <span style="white-space:pre"></span>if (!isSecure(s)) { <span style="white-space:pre"></span>throw new SecurityException(); <span style="white-space:pre"></span>}    <span style="white-space:pre"></span>//here will cause problem, if s is changed before this by using other references.        <span style="white-space:pre"></span>causeProblem(s);<span style="white-space:pre"></span>}
5.不可变对象是天然线程安全的

因为不可变对象不能被修改,因此可以在多个线程间共享而不用进行任何同步的操作。


简单来说,String被设计为不可变类的原因就是效率和安全。这也是它被广泛使用的原因之一。


0 0
原创粉丝点击