Java中的String为何要设计成不可变的?

1、不可变类和不可变对象

Normally,you create an object and allow its contents to be changed later.However ,occasionally it is desirable to create an object whose contents cannot be changed once the object has been created.We call such an object as immutable object and its class as immutable class.html

建立一个一旦其内容就不能在改变的对象,称其为一个不可变对象(immutable object),而它的类称为不可变类(immutable class)。程序员

 JDK中String的源码数据库

public final class String implements Serializable, Comparable<String>, CharSequence { /** The value is used for character storage. */ private final char[] value; /** Cache the hash code for the string */ private int hash;// Default to 0

能够看到String的本质是一个char数组,是对字符串数组的封装,而且是被final修饰的,建立后不可改变。数组

2、String类不可变性的好处

一、便于实现字符串池(String pool)

在Java中,因为会大量的使用String常量,若是每一次声明一个String都建立一个String对象,那将会形成极大的空间资源的浪费。Java提出了String pool的概念,在堆中开辟一块存储空间String pool,当初始化一个String变量时,若是该字符串已经存在了,就不会去建立一个新的字符串变量,而是会返回已经存在了的字符串的引用。缓存

String a = "Hello world!";
String b = "Hello world!";

若是字符串是可变的,某一个字符串变量改变了其值,那么其指向的变量的值也会改变,String pool将不可以实现!安全

二、使多线程安全

 看下面这个场景,一个函数appendStr()在不可变的String参数后面加上一段“bbb”后返回。appendSb()负责在可变的StringBuilder后面加"bbb"。网络

public class test { // 不可变的String public static String appendStr(String s) { s += "bbb"; return s; } // 可变的StringBuilder public static StringBuilder appendSb(StringBuilder sb) { return sb.append("bbb"); } public static void main(String[] args) { String s = new String("aaa"); String ns = test.appendStr(s); System.out.println("String aaa>>>" + s.toString()); // StringBuilder作参数 StringBuilder sb = new StringBuilder("aaa"); StringBuilder nsb = test.appendSb(sb); System.out.println("StringBuilder aaa >>>" + sb.toString()); } }

若是程序员不当心像上面例子里,直接在传进来的参数上加上“bbb”.由于Java对象参数传的是引用,全部可变的StringBuffer参数就被改变了。能够看到变量sb在Test.appendSb(sb)操做以后,就变成了"aaabbb"。
有的时候这可能不是程序员的本意。因此String不可变的安全性就体如今这里。多线程

在并发场景下,多个线程同时读一个资源,是安全的,不会引起竞争,但对资源进行写操做时是不安全的,不可变对象不能被写,因此保证了多线程的安全。并发

The advantage of immutability comes with concurrency. It is difficult to maintain correctness in mutable objects, as multiple threads could be trying to change the state of the same object, leading to some threads seeing a different state of the same object, depending on the timing of the reads and writes to the said object.
By having an immutable object, one can ensure that all threads that are looking at the object will be seeing the same state, as the state of an immutable object will not change.app

三、避免安全问题

在网络链接和数据库链接中字符串经常做为参数,例如,网络链接地址URL,文件路径path,反射机制所须要的String参数。其不可变性能够保证链接的安全性。若是字符串是可变的,黑客就有可能改变字符串指向对象的值,那么会引发很严重的安全问题。

由于String是不可变的,因此它的值是不可改变的。但因为String不可变,也就没有任何方式能修改字符串的值,每一次修改都将产生新的字符串,若是使用char[]来保存密码,仍然可以将其中全部的元素设置为空和清零,也不会被放入字符串缓存池中,用字符串数组来保存密码会更好。

四、加快字符串处理速度

因为String是不可变的,保证了hashcode的惟一性,因而在建立对象时其hashcode就能够放心的缓存了,不须要从新计算。这也就是Map喜欢将String做为Key的缘由,处理速度要快过其它的键对象。因此HashMap中的键每每都使用String。

在String类的定义中有以下代码:

private int hash;//用来缓存HashCode

整体来讲,String不可变的缘由要包括 设计考虑,效率优化,以及安全性这三大方面。

 

https://blog.csdn.net/jiahao1186/article/details/81150912

https://blog.csdn.net/u012546526/article/details/44458185

https://blog.csdn.net/hyddhy/article/details/87105691

https://www.cnblogs.com/wcyBlog/p/4073725.html、

相关文章
相关标签/搜索