Java有字符串池,因此String类的对象是不可变的。
但我的问题仍然存在 -
为什么需要创建String POOL?
为什么String类不能像其他类一样持有自己的值?
是否内部JVM需要一些字符串或者这是性能上的好处。如果是,那么如何实现的呢?
Java有字符串池,因此String类的对象是不可变的。
但我的问题仍然存在 -
为什么需要创建String POOL?
为什么String类不能像其他类一样持有自己的值?
是否内部JVM需要一些字符串或者这是性能上的好处。如果是,那么如何实现的呢?
由于字符串是不可变的,所以可以使用池。但是字符串的不可变性不仅仅因为池而决定。不可变性还有许多其他好处。顺便说一下,Double
也是不可变的,但没有 Double 的池。
需要字符串池是为了减少程序使用的所有字符串字面量(和 interned 字符串)占用的内存,因为这些字面量很可能在程序的许多地方被多次使用。你只需引用同一个字符串对象,而不是拥有成千上万个相同的字符串字面量副本,这样可以减少内存使用。
请注意,String 类与其他类没有区别:它持有自己的 char 数组。当调用 substring 时,它也可能与其他 String 实例共享该数组。
当编译器发现需要创建一个新的字符串字面量时,它首先检查池中是否存在相同的字符串,如果找到则不会创建新的字符串字面量,而是引用现有的字符串。
将字符串设为不可变的好处是安全性特性。请阅读以下内容
为什么Java中的字符串被设置为不可变?
尽管性能也是一个原因(假设您已经了解了维护内部字符串池以确保多次使用相同的字符串对象而无需创建/回收它们的原理),但Java中将字符串设置为不可变的主要原因是“安全性”。惊讶吗?让我们了解一下为什么。
假设您需要打开一个需要用户进行身份验证的安全文件。假设有两个名为“user1”和“user2”的用户,他们分别拥有自己的密码文件“password1”和“password2”。显然,“user2”不应该访问“password1”文件。
正如我们所知道的,在Java中,文件名是通过使用字符串指定的。即使您创建了一个“File”对象,您也只能将文件名作为字符串传递,并且该字符串在File对象内部作为其成员之一维护。
如果String是可变的,'user1'可以使用自己的凭据登录,然后在JVM实际执行本机操作系统调用打开文件之前,以某种方式成功将密码文件名(一个String对象)从'password1'更改为'password2'。这将允许'user1'打开user2的密码文件。可以理解的是,这将导致Java中的一个严重安全漏洞。我知道这里有很多“可能会”的情况,但您肯定会同意,这将打开一个门,允许开发人员故意或无意地破坏许多资源的安全性。String str = new String("stackoverflow");
String s1 = new String("hello").intern();
String s2 = "hello";
System.out.println(s1 == s2); // true , because now s1 is in SP