Java有字符串池,因为字符串类的对象是不可变的。
但我的问题是 -
制作String POOL需要什么?
为什么字符串类不能像其他类一样保存自己的值?
内部JVM是否需要一些字符串,或者这是性能优势。如果是的话怎么样?
答案 0 :(得分:6)
可以使用池,因为字符串是不可变的。但是String的不变性还没有仅仅因为这个池而决定。不变性还有许多其他好处。顺便说一下,Double
也是不可变的,没有双打池。
字符串池的需求是减少保存程序使用的所有字符串文字(以及实习的字符串)所需的内存,因为这些文字在程序的许多地方很有可能被多次使用。您只需要对同一个字符串进行数千个引用,而不是拥有相同字符串文字的数千个副本,这样可以减少内存使用量。
请注意,String类与其他类没有区别:它拥有自己的char数组。但是,当调用substring时,它也可能与其他String实例共享它。
答案 1 :(得分:2)
请参阅以下链接:
Questions about Java's String pool
Some queries regarding Java String Pool
Regarding Java String Constant Pool
,你会得到答案。
在一句话中,答案是to use JVM memory cleaverly
答案 2 :(得分:1)
制作 String POOL 的需要是什么?
创建时,一个 String 对象存储在堆中,而在构造函数中发送的 String 字面量存储在 SP 中。这就是为什么使用 String 对象不是一个好的做法。因为它创建了两个对象。
String str = new String("stackoverflow");
上面的 str 与引用 str 一起保存在堆中,来自构造函数的字符串字面量 -"stackoverflow" - 存储在 String Pool 中。这对性能不利。两个对象被装箱。
流程:创建一个字符串字面量 -> JVM 在字符串池中查找值,以确定是否存在相同的值(没有要返回的对象) -> 找不到值 -> 字符串字面量是创建为一个新对象(内部使用 new 关键字)-> 但现在不发送到堆,而是发送到字符串池中。
区别在于使用 new 关键字创建对象的位置。如果它是由程序员创建的,它将直接发送堆中的对象,没有延迟。如果它是在内部创建的,则它会被发送到 String Poll。这是由方法 intern() 完成的。 intern() 在声明字符串文字时在内部调用。并且此方法是在 SP 中搜索与返回现有 String 对象的引用或/并将对象发送给 SP 相同的值。
当用 new 创建一个 String obj 时,不会调用 intern() 并且对象存储在堆中。但是你可以在 String obj 上调用 intern(): String str = new String().intern();现在 str 对象将存储在 SP 中。 例如:
String s1 = new String("hello").intern();
String s2 = "hello";
System.out.println(s1 == s2); // true , because now s1 is in SP
答案 3 :(得分:0)
当我们编译器看到必须创建一个新的字符串文字时,它首先检查池是否有相同的字符串,如果找不到新的字符串文字,则引用现有的字符串。
答案 4 :(得分:0)
使字符串成为不可变的好处是安全功能。请阅读以下
为什么String已在Java中变为不可变?
虽然,性能也是一个原因(假设您已经知道维护内部字符串池,以确保多次使用相同的String对象而不必多次创建/重新声明它),但String在Java中变为不可变的主要原因是“安全性”。惊讶吗?让我们理解为什么。
假设您需要打开一个安全文件,要求用户对自己进行身份验证。假设有两个用户名为“user1”和“user2”,他们分别拥有自己的密码文件“password1”和“password2”。显然'user2'不应该访问'password1'文件。
我们知道Java中的文件名是使用字符串指定的。即使您创建了一个“文件”对象,也只能将该文件的名称作为字符串传递,并将该字符串作为其成员之一保存在File对象中。
如果String是可变的,'user1'可能已经使用他的凭据登录,然后以某种方式可以设法将其密码文件名(String对象)的名称从'password1'更改为'password2',然后JVM实际放置本机OS系统调用打开文件。这将允许'user1'打开user2的密码文件。可以理解,这会导致Java中存在严重的安全漏洞。我知道有很多'可以在这里,但你肯定会同意它会打开一扇门,允许开发人员有意或无意地搞乱许多资源的安全性。
在Strings不可变的情况下,JVM可以确保相应File对象的文件名实例成员将继续指向同一个未更改的“filename”String对象。无论如何,作为File类中的'final'的'filename'实例成员不能被修改为指向任何其他String对象,指定除预期文件之外的任何其他文件(即,用于创建File对象的文件)。