为什么 String 要设计成 Final 类?

题目

为什么 String 要设计成 Final 类?

推荐解析

1)只有当字符串是不可变的,字符串池才有可能实现

字符串池的实现可以在运行时节约很多 heap 空间,因为不同的字符串变量都指向池中的同一个字符串。但如果字符串是可变的,那么 String interning 将不能实现(注:String interning 是指对不同的字符串仅仅只保存一个,即不会保存多个相同的字符串。),因为这样的话,如果变量改变了它的值,那么其它指向这个值的变量的值也会一起改变。

String str1 = "Hello";
String str2 = "Hello";
System.out.println(str1 == str2); // 输出 true,因为字符串池中已经存在了 "Hello"

2)如果字符串是可变的,那么会引起很严重的安全问题

譬如,数据库的用户名、密码都是以字符串的形式传入来获得数据库的连接。因为字符串是不可变的,所以它的值是不可改变的,否则黑客们可以钻到空子,改变字符串指向的对象的值,造成安全漏洞。

3)因为字符串是不可变的,所以是多线程安全的

同一个字符串实例可以被多个线程共享。这样便不用因为线程安全问题而使用同步。字符串自己便是线程安全的。

String str = "Hello";
new Thread(() -> System.out.println(str)).start();
new Thread(() -> System.out.println(str)).start();

4)类加载器要用到字符串,不可变性提供了安全性,以便正确的类被加载

譬如你想加载 Java.util.Long 类,而这个值被改成了 haha.Long,那么会对你的数据库造成不可知的破坏。

Class<?> clazz = Class.forName("java.lang.String");

5)作为 Map 的 key,提高了访问效率

在Java中,字符串是不可变的,所以它们的 hashcode 在创建时就被缓存了,不需要重新计算。这就使得字符串很适合作为 Map 中的键。

其他补充

鱼聪明 AI 的回答:

鱼聪明 AI 地址:https://www.yucongming.com/

在Java中,String类被设计为final类,主要有以下几个原因:

  1. 安全性String类是不可变的,这意味着一旦创建,其值就不能被改变。这对于安全性来说是非常重要的,因为你可以安全地将敏感信息的一部分作为String对象的一部分,而不必担心它们会被修改。如果String类不是final的,那么你可能会创建一个子类,这个子类可能会修改String对象的值,这将破坏String类的不变性。

  2. 性能String类是不可变的,这意味着它的实例可以被多个线程安全地共享,而不需要使用额外的同步机制。这对于性能来说是非常重要的,因为在多线程环境中,频繁的同步操作可能会导致性能下降。

  3. 避免混淆:如果String类不是final的,那么你可能会创建一个子类,这个子类可能会改变String对象的行为。这将导致混淆,因为你可能不确定一个String对象的行为是由String类本身定义的,还是由它的子类定义的。通过将String类设计为final,你可以避免这种混淆。

  4. 避免继承导致的问题:如果String类不是final的,那么你可能会创建一个子类,这个子类可能会改变String对象的行为。这将导致一些问题,例如,如果你创建了一个子类,并将它与String对象进行比较,那么你可能会得到一个意外的结果。通过将String类设计为 final,你可以避免这些问题。

总的来说,String类被设计为final类,是为了保证它的安全性、性能和行为的一致性。

CSDN 某同学的回答:

一旦 string 类可改变了。将违背 java 设计规则,即 hashcode 不同,equals 一定也不同。hashcode 相同,equals 可能相同。违背设计规则后,很多类的特性将失效。比如 set 集合,是不允许出现重复数据的。而强行改变 s 的值后,set 不许出现重复数据的特性将失效。

推荐文章

CSDN博客:https://blog.csdn.net/efggfxfvhh/article/details/126520262

欢迎交流

通过阅读本文,你应该知道了为什么 String 要设计成 final 类,面试中你可能会回答为什么 String 不能被重写,String 底层原理是什么?但是关于为什么会被设计成 final 类可能会缺少了解,本文将会对你有所帮助。我在下面抛出以下几个问题,欢迎大家在评论区进行留言!

1.除了 String 类,Java 中还有哪些类被设计为 final 类?

2.在多线程环境中,如果 String 类不是 final,那么它的实例是否可以被多个线程安全共享?

3.如果 String 类不是 final 的,那么它的子类是否可以被用于替代 String 类?