为什么String类在Java中声明为final?

从我得知java.lang.String类在Java中被声明为final时,我想知道为什么会这样? 我当时没有找到答案,但是这篇文章:如何在Java中创建String类的副本? 提醒了我的查询。

当然,String提供了我所需要的所有功能,并且从来没有想过任何需要扩展类String的操作,但是你永远不会知道某人可能需要什么!

那么,有没有人知道设计师决定什么时候决定做最终决定?


将字符串实现为不可变对象是非常有用的。 你应该阅读关于不变性的内容以更多地了解它。

不可变对象的一个优点是

您可以通过将它们指向单个实例来共享重复项。

(从这里)。

如果字符串不是最终的,你可以创建一个子类,并有两个字符串看起来相似时,“看作字符串”,但实际上是不同的。


这是一篇很好的文章,概述了上述答案中已经提到的两个原因:

  • 安全性 :系统可以发布敏感的只读信息,而不用担心它们会被更改
  • 性能 :不变数据对于使事物线程安全非常有用。
  • 这可能是该文章中最详细的评论。 它与Java中的字符串池和安全问题有关。 它关于如何确定进入字符串池的内容。 假设两个字符串在角色序列相同的情况下都是相等的,那么我们就会遇到一个竞争条件,让谁先到达那里并且伴随着它的安全问题。 如果不是,那么字符串池将包含冗余字符串,从而失去了首先将其放在首位的好处。 只是自己读出来,会吗?


    扩展字符串会对等于和实习生造成破坏。 JavaDoc说等于:

    将此字符串与指定的对象进行比较。 当且仅当参数不为null并且是表示与此对象相同字符序列的String对象时,结果为true。

    假设java.lang.String不是最终的, SafeString可以等于一个String ,反之亦然; 因为他们会代表相同的字符序列。

    如果您将intern应用于SafeString会发生什么情况 - SafeString会进入JVM的字符串池吗? ClassLoaderSafeString持有的所有对象引用将在JVM的生命周期中锁定到位。 你会得到一个关于谁可能是第一个实习一系列角色的竞赛条件 - 也许你的SafeString会赢,也许是一个String ,或者是一个不同的类加载器(因此是不同的类)加载的SafeString

    如果你赢了比赛,这将是一个真正的单身人士,人们可以通过反射和secretKey.intern().getClass().getClassLoader()来访问整个环境(沙箱secretKey.intern().getClass().getClassLoader()

    或者JVM可以通过确保只有具体的String对象(并且没有子类)被添加到池中来阻止这个漏洞。

    如果equals被实现为SafeString != String那么SafeString.intern != String.internSafeString必须被添加到池中。 然后,池将成为<Class, String>而不是<String>的池,并且您需要输入池的所有内容都将成为新的类加载器。


    String是不可变的或最终的绝对最重要的原因在于它被类加载机制使用,因此具有深刻而根本的安全性方面。

    如果String是可变的或不是最终的,加载“java.io.Writer”的请求可能已被更改为加载“mil.vogoon.DiskErasingWriter”

    参考:为什么String在Java中是不可变的

    链接地址: http://www.djcxy.com/p/23871.html

    上一篇: Why is String class declared final in Java?

    下一篇: Same Serial version id for all the classes?