为什么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的字符串池吗? ClassLoader
和SafeString
持有的所有对象引用将在JVM的生命周期中锁定到位。 你会得到一个关于谁可能是第一个实习一系列角色的竞赛条件 - 也许你的SafeString
会赢,也许是一个String
,或者是一个不同的类加载器(因此是不同的类)加载的SafeString
。
如果你赢了比赛,这将是一个真正的单身人士,人们可以通过反射和secretKey.intern().getClass().getClassLoader()
来访问整个环境(沙箱secretKey.intern().getClass().getClassLoader()
。
或者JVM可以通过确保只有具体的String对象(并且没有子类)被添加到池中来阻止这个漏洞。
如果equals被实现为SafeString
!= String
那么SafeString.intern
!= String.intern
和SafeString
必须被添加到池中。 然后,池将成为<Class, String>
而不是<String>
的池,并且您需要输入池的所有内容都将成为新的类加载器。
String是不可变的或最终的绝对最重要的原因在于它被类加载机制使用,因此具有深刻而根本的安全性方面。
如果String是可变的或不是最终的,加载“java.io.Writer”的请求可能已被更改为加载“mil.vogoon.DiskErasingWriter”
参考:为什么String在Java中是不可变的
链接地址: http://www.djcxy.com/p/23871.html