String
类被设计为final
的主要原因可以总结如下:
- 安全性:防止字符串内容被意外或恶意修改,确保类加载器和其他安全敏感操作的安全性。
- 性能:通过字符串池、和哈希码缓存提高性能。
- 线程安全:不可变对象天然线程安全,无需额外同步。
- 一致性:避免继承带来的复杂性,保持类的行为一致性。
主要从:缓存、安全性、线程安全、性能这4个角度来考虑。
性能
字符串是使用最广泛的数据结构,大量的字符串的创建是非常耗费资源的。
所以,Java在内存中维护一个字符串池,用于重用相同的字符串。
通过重用相同内容的字符串对象,避免创建大量重复的字符串对象,减少内存消耗。
如下例子,只会创建一个字符串,而不是两个:
String s1 = "abc"; String s2 = "abc";
当使用字面值创建字符串时,JVM会首先检查字符串池中是否已经存在这个字符串。
如果字符串池中已经存在这个字符串,s1
和s2
会引用同一个对象。
如果字符串是可变的,修改一个一个引用的字符串值将会导致另一个引用值也发生变化,这明显是不可以的。
所以,String
类被设计为final
,就防止了这样的情况出现。
安全性
String
类是不可变的,意味着一旦创建了一个String
对象,其值就不能被改变。
这对于安全性至关重要,特别是在需要使用String
对象进行敏感操作时,例如:
密码和敏感数据:当密码被存储为字符串时,不可变性确保密码值不会在内存中被意外、或恶意修改。
Class加载:类加载器使用类名字符串来加载类,通过确保字符串不可变,可以防止恶意代码替换类名字符串,从而确保加载的类是预期的类。
线程安全
不可变对象天然是线程安全的,因为它们的状态在创建后不会改变,多个线程可以安全地共享不可变对象而不需要同步控制。
对于String
类来说,这意味着字符串对象在多线程环境中使用时不需要额外的同步措施,从而避免了潜在的并发问题。
哈希码缓存
由于String
对象是不可变的,其哈希码可以在第一次计算后缓存,以后每次调用hashCode()
方法时都可以直接返回缓存的哈希码。
这提高了String
对象在哈希集合(如HashMap
和HashSet
)中的性能。
一致性
将String
类设计为final
可以避免继承带来的复杂性。
通过禁止继承,Java的设计者确保了String
类的行为不会被子类修改,从而保持了一致性和预期的行为。
mikechen
mikechen睿哥,10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。
关注「mikechen」公众号,获取更多技术干货!

后台回复【架构】即可获取《阿里架构师进阶专题全部合集》,后台回复【面试】即可获取《史上最全阿里Java面试题总结》