String在Java中是不可变的。不可变类只是其实例无法修改的类。创建实例时实例中的所有信息都会初始化,并且无法修改该信息。不变类有很多优点。本文总结了为什么String被设计为不可变的。这篇文章从内存,同步和数据结构的角度说明了不变性概念。
1.字符串池的要求
字符串池(String intern pool)是“ 方法区”中的特殊存储区。创建字符串时,如果该字符串已存在于池中,则将返回现有字符串的引用,而不是创建新对象。
以下代码将在堆中仅创建一个字符串对象。
String string1 = "abcd";
String string2 = "abcd";
外观如下:
如果字符串是可变的,则用一个引用更改字符串会导致其他引用的值错误。
2.缓存哈希码
字符串的哈希码在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.安全性
字符串被广泛用作许多Java类的参数,例如网络连接,打开文件等。如果字符串不是不可变的,则连接或文件将被更改,这可能会导致严重的安全威胁。该方法认为它正在连接到一台机器,但没有。因为参数是字符串,所以可变字符串也可能在反射中引起安全问题。
这是一个代码示例:
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技术很感兴趣也可以交流学习,Java技术资料交流qq裙:907135806,共同学习进步。
不要再用"没有时间“来掩饰自己思想上的懒惰!趁年轻,使劲拼,给未来的自己一个交代!
还有奉上我近期整理出来的一套完整的java架构思维导图,可供大家对照知识点参考学习。