一个人至少拥有一个梦想,有一个理由去坚强

心若没有栖息的地方,到哪里都是在流浪

java基础系列02 | [字符串和数组] 为什么String在Java中是不可变的?

String 在java中是不变的。不可变类只是一个它的实例不能被改变的类。创建实例时,将初始化实例中的所有信息,并且无法修改信息。不可变类有很多优点。本文总结了为什么String被设计为不可变的原因。这篇文章从内存(memory)、同步( synchronization)和数据结构(data structures)的角度说明了不变性概念。

1、字符串池(String Pool)的要求

字符串池(String intern pool)是方法区域中的特殊存储区域。当创建字符串并且池中已存在该字符串时,将返回现有字符串的引用,而不是创建新的对象。

下面代码将在堆中仅创建一个字符串对象。

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

下面这幅图可直观体现:

 

《java基础系列02 |  [字符串和数组] 为什么String在Java中是不可变的?》

如果字符串是可变的,则使用一个引用更改字符串将导致其他的引用的值错误。

2、缓存hashcode

字符串的哈希码(hashcode)经常在java中使用。例如,在HashMap或HashSet中。不可变性保证哈希码总是相同的,这样它就可以缓存而不用担心变化。这意味着,每次使用都不需要计算哈希码。这更有效率。

在String 类中,有以下的代码:

private int hash;//this is used to cache 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包含非重复元素)。当然,上面的示例仅仅是用来演示的目的,真正字符串类中根本没有value字段哦。

4、安全

String被广泛用作许多java类的参数,例如网络连接,打开文件等。如果String不是不可变的,则会更改连接或文件,这可能会导致严重的安全威胁。该方法认为它已经连接到一台机器,但事实并非如此。可变字符串也可能在Reflection中引起安全问题,因为参数是字符串。

下面示例代码:

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之所以设计为不可变的,主要是出于效率和安全原因。这也正是在一般情况下很多地方,不可变类被优先选择的主要原因。

 

 

更多精彩,请扫码关注我的微信公众号!

《java基础系列02 |  [字符串和数组] 为什么String在Java中是不可变的?》

 

点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注