文章目录

String被设计为不可变是因为String对象是缓存在字符串池中的,因此这些缓存的字符串是可以被多个客户端访问的,如果一个客户端的访问影响了别的客户端的行为,这样就存在风险。例如一个客户端把"test"改为"TEST",其他所有的客户端都会跟着受影响。之所以把String进行了缓存处理,是出于性能的考虑。因此这个风险只能通过把String设置为不可变来避免。同时,String类被声明为final的。是防止其他人通过继承String类,覆盖父类的方法,会破坏String的不可变性、缓存性以及hascode的计算方式。

另一个String不可变的原因是由于HashMap。由于HashMap是基于hash规则,只有相同的对象有相同的Hash值,他才能运行良好。而人们又非常流行把String作为HashMap的键值,如果String可变,就会产生不同的Hash值,只有String不可变,才能取回存在HashMap中的值。

String被广泛用于Java类的参数,例如你可以通过把ip和端口的字符串作为参数打开一个网络连接,你可以通过把URL的字符串作为参数来打开一个数据库连接,你可以传一个文件名字符串作为参数,通过JAVA I/O类来打开一个文件。在这些例子中,如果String是可变的,就会导致严重的安全威胁,别人可以通过恶意的修改缓存的字符来访问所有你已经有授权的文件。通过把String设计为不可变的,就避免了这样的威胁。

对于多线程变成来说,由于String的不可变性,你可以安全的在多个重要的线程中共享String,不会造成线程同步问题。

另一个重要原因,是String的不可变性为Java的类加载机制的安全性提供了根本的保障。如果String是可变的,一个加载"java.io.Writer" 类的请求,可以被改变为"mil.vogoon.DiskErasingWriter",这样安全就没有保障了。