不可变字符串
最近一直在学习Java的相关知识,看到不可变字符串这一知识点,乍一看有些难以理解。通过一些思考以及资料的整理,在此博客对这一知识点加以概括。
- 字符串
- 不可变字符串
- 不可变的优势
1.字符串
在Java中String是一个类,其对象被存储在StringPool中,StringPool是堆内存中一块特殊的存储区域。当我们为一个引用变量赋字符串对象x时,会查找StringPool中是否存在x,若已经存在,则不必再开辟新的内存空间,直接指向x,即共享对象。若不存在,则开辟一块新的内存并且初始化x,再将引用变量指向x。例如:
String a="White";
String b="White";
String c="Black";
这里的引用变量a和b指向的是堆内存中的同一个对象,值为“White”,二者共享此对象。而引用变量c则重新创建了一个字符串对象,值为“Black”。
2.不可变字符串
一个String 对象的内容是不可变(immutable)的,当你对String 进行修改, 其实他是创建了新的字符串对象,然后将它的引用赋值给了原来的引用变量,这样原来的对象就再也不能访问了,因为他之前的引用已经弃他而去指向了新的字符串对象。他只能等着JVM(Java虚拟机)的自动回收。例如:
String a="White";
a="Black";
这里执行第二条语句的时候,并不是把a的值从“White”改成了“Black”,而是重新创建了一个String对象,值为“Black”,再把它的引用赋给引用变量a,原来值为“White”的对象没有被其他引用变量引用,最后会被JVM回收。
还有一种情况,如下:
String a="White";
String b=new String("White");
String c="White";
这里a和c指向同一个String对象,而b和a、c的创建方式不同,所以b和a、c指向的是不同对象,尽管他们的content相同。
可以看出String对象只能被创建或被回收,其值是不能被改变的,因此称为不可变字符串。
3.不可变字符串的优势
Java面试题中有个非常常见的问题就是“什么是不可变对象”,它有什么好处,在什么情况下使用,或者更具体些,Java的String类为什么要设成immutable类型?
事实上,相对于可变对象,不可变对象的优势主要在于:
(1)不可变对象可以提高String Pool的效率。由于String对象是不可变的,当我们操作这个对象时,就不必再引用这个对象本身,而只需引用它的地址即可。通常一个地址所占内存较小,因此操作起来效率就高。
(2)不可变对象对于多线程是安全的。在多线程同时进行的情况下,一个可变对象的值如果发生了改变,同时此对象又是被其他进程共享的,就会发生不可预知的错误,而不可变对象则可以很好的避免这个问题。
(3)StringPool的需要。StringPool中存放了许多String对象,其中就会存在多个引用变量引用同一个对象的情况。如果该对象是可变的,将会导致其他共享此对象的引用变量的对象值也会发生改变,也会引起一些不可预期的问题。
(4)允许String对象缓存HashCode。Java中String对象的哈希码被频繁地使用, 字符串不变性保证了hash码的唯一性,因此可以放心地进行缓存.这也是一种性能优化手段,意味着不必每次都去计算新的哈希码。
(5)不可变对象可以保证安全性。如果字符串是可变的,那么会引起很严重的安全问题。譬如,数据库的用户名、密码都是以字符串的形式传入来获得数据库的连接,或者在socket编程中,主机名和端口都是以字符串的形式传入。因为字符串是不可变的,所以它的值是不可改变的,所以安全,否则黑客们可以钻到空子,改变字符串指向的对象的值,造成安全漏洞。
不骄才能师人之长,而自成其学。 --------------谭嗣同
本文所涉及的链接并非自己所写,仅供大家学习和参考。