String类为什么是final的?

String类被设计为final的主要原因可以总结如下:

  • 安全性:防止字符串内容被意外或恶意修改,确保类加载器和其他安全敏感操作的安全性。
  • 性能:通过字符串池、和哈希码缓存提高性能。
  • 线程安全:不可变对象天然线程安全,无需额外同步。
  • 一致性:避免继承带来的复杂性,保持类的行为一致性。

主要从:缓存、安全性、线程安全、性能这4个角度来考虑。

性能

字符串是使用最广泛的数据结构,大量的字符串的创建是非常耗费资源的。

所以,Java在内存中维护一个字符串池,用于重用相同的字符串。

通过重用相同内容的字符串对象,避免创建大量重复的字符串对象,减少内存消耗。

如下例子,只会创建一个字符串,而不是两个:

String s1 = "abc";
String s2 = "abc";

String类为什么是final的?-mikechen

 

当使用字面值创建字符串时,JVM会首先检查字符串池中是否已经存在这个字符串。

如果字符串池中已经存在这个字符串,s1s2会引用同一个对象。

如果字符串是可变的,修改一个一个引用的字符串值将会导致另一个引用值也发生变化,这明显是不可以的。

所以,String类被设计为final,就防止了这样的情况出现。

 

安全性

String类是不可变的,意味着一旦创建了一个String对象,其值就不能被改变。

这对于安全性至关重要,特别是在需要使用String对象进行敏感操作时,例如:

密码和敏感数据:当密码被存储为字符串时,不可变性确保密码值不会在内存中被意外、或恶意修改。

Class加载:类加载器使用类名字符串来加载类,通过确保字符串不可变,可以防止恶意代码替换类名字符串,从而确保加载的类是预期的类。

 

线程安全

不可变对象天然是线程安全的,因为它们的状态在创建后不会改变,多个线程可以安全地共享不可变对象而不需要同步控制。

对于String类来说,这意味着字符串对象在多线程环境中使用时不需要额外的同步措施,从而避免了潜在的并发问题。

 

哈希码缓存

由于String对象是不可变的,其哈希码可以在第一次计算后缓存,以后每次调用hashCode()方法时都可以直接返回缓存的哈希码。

这提高了String对象在哈希集合(如HashMapHashSet)中的性能。

 

一致性

String类设计为final可以避免继承带来的复杂性。

通过禁止继承,Java的设计者确保了String类的行为不会被子类修改,从而保持了一致性和预期的行为。

mikechen

mikechen睿哥,10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。

关注「mikechen」公众号,获取更多技术干货!

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

评论交流
    说说你的看法