1、典型回答
对于这个问题,Java之父詹姆斯 ·高斯林(James Gosling) 是这样回答的:
I would use an immutable whenever I can
翻译为中文:只要允许,我就会使用不可变对象
而作为普通人的我们来说,理解 String 为什么要用 final 来修饰,可以从以下方面入手:
1、安全性:由于 String 是不可变类,即不能被修改,所以使用 final 修饰可以确保 String 类的内部结构不能被修改,从而保证了 String 的数据的安全性。例如这幅图中的 “0X1010”,系统中只要认定这个指针之后,它就不能被改变了,从而就保证了其安全性(但是,需要注意的是,安全这个概念永远是相对的,没有绝对的安全,所以不要死扣字眼)
2、线程安全性:String 是不可变的,因此多个线程可以同时访问和共享 String 对象,而无需进行额外的同步措施。这样可以提高程序的并发性能并减少线程安全问题的出现。线程不安全是由于,多个线程同时修改同一个变量才会导致线程安全问题,而 String 是不可变的,每次操作的都是新对象,那么多个线程操作的就是各自的新对象了,那么就不会有线程安全问题了
3、用作键值的准确性:由于 String 的不可变性,它可以安全地用作 HashMap、HashSet 等集合类的键值,这样可以确保散列算法的准确性,避免因修改 String 对象导致哈希值发生变化的情况
4、性能:String 类在许多地方被广泛使用,使用 final 修饰可以使编译器在编译时对 String 类进行一些优化,从而提高程序的执行效率
2、全面剖析
使用 final 修饰 String 可以保证安全性、线程安全性、可稳定的用作键值和提供程序性能
在 String 的源码实现中,不单单是类使用 final 修饰,其中的很多属性也使用了 final 进行修饰了,如下所示:
3、知识扩展
String 既然是不可变的,那么它的 “+” 操作是怎么实现的呢?
String “+” 操作底层实现
当我们将字符串反编译的时候,就能看出 String的 “+” 操作是怎么实现了,例如以下代码:
以上代码反编译的代码如下(使用 jad 反编译):
从上述代码可以看出,String的 “+” 操作是使用 StringBuilder 的 append 来实现的
String、StringBuilder、StringBuffer 有什么区别?-CSDN博客