我对Java中的StringPool感到困惑.我在阅读Java中的String章节时遇到过这个问题.请以外行的方式帮助我理解StringPool实际上做了什么.
Nik*_*bak 121
这打印true
(即使我们不使用equals
方法:比较字符串的正确方法)
String s = "a" + "bc";
String t = "ab" + "c";
System.out.println(s == t);
Run Code Online (Sandbox Code Playgroud)
当编译器优化您的字符串文字时,它会看到两者s
并且t
具有相同的值,因此您只需要一个字符串对象.它是安全的,因为String
它在Java中是不可变的.
作为结果,双方s
并t
指向同一个对象,一些小的内存保存.
名称"字符串池"来自这样的想法,即所有已定义的字符串都存储在某个"池"中,并且在创建新的String
对象编译器之前检查是否已定义此类字符串.
MSt*_*odd 36
我不认为它实际上做得太多,看起来它只是字符串文字的缓存.如果你有多个字符串的值是相同的,它们都将指向字符串池中相同的字符串文字.
String s1 = "Arul"; //case 1
String s2 = "Arul"; //case 2
Run Code Online (Sandbox Code Playgroud)
在案例1中,文字s1是新创建的并保存在池中.但在案例2中,文字s2引用s1,它不会创建新的.
if(s1 == s2) System.out.println("equal"); //Prints equal.
String n1 = new String("Arul");
String n2 = new String("Arul");
if(n1 == n2) System.out.println("equal"); //No output.
Run Code Online (Sandbox Code Playgroud)
http://p2p.wrox.com/java-espanol/29312-string-pooling.html
cHa*_*Hao 17
当JVM加载类或以其他方式查看文字字符串或某些代码intern
字符串时,它会将字符串添加到一个隐藏最多的查找表中,该查找表具有每个此类字符串的一个副本.如果添加了另一个副本,则运行时会对其进行排列,以便所有文字引用相同的字符串对象.这被称为"实习".如果你说的话
String s = "test";
return (s == "test");
Run Code Online (Sandbox Code Playgroud)
它会返回true
,因为第一个和第二个"测试"实际上是同一个对象.实习字符串这样比较可以了,多比快String.equals
,因为有一个单一的基准进行比较,而不是一堆char
比较.
您可以通过调用将一个字符串添加到池中String.intern()
,这将为您提供字符串的池化版本(可能是您正在实习的相同字符串,但您可能会疯狂地依赖它 - 您经常可以'确切地确定已经加载了什么代码并且直到现在运行并且实际上是相同的字符串).池化版本(从中返回的字符串intern
)将等于任何相同的文字.例如:
String s1 = "test";
String s2 = new String("test"); // "new String" guarantees a different object
System.out.println(s1 == s2); // should print "false"
s2 = s2.intern();
System.out.println(s1 == s2); // should print "true"
Run Code Online (Sandbox Code Playgroud)
And*_*s_D 17
让我们从虚拟机规范的引用开始:
加载包含String文字的类或接口可能会创建一个新的String对象(第2.4.8节)来表示该文字.如果已经创建了一个String对象来表示该文字的上一个匹配项,或者如果已在表示与该文字相同的字符串的String对象上调用了String.intern方法,则可能不会发生这种情况.
这可能不会发生 - 这是一个暗示,String
对象有一些特殊之处.通常,调用构造函数将始终创建该类的新实例.字符串不是这种情况,尤其是在使用文字"创建"String对象时.这些字符串存储在全局存储(池)中 - 或者至少引用保存在池中,并且每当需要已知字符串的新实例时,vm将从池中返回对该对象的引用.在伪代码中,它可能是这样的:
1: a := "one"
--> if(pool[hash("one")] == null) // true
pool[hash("one") --> "one"]
return pool[hash("one")]
2: b := "one"
--> if(pool[hash("one")] == null) // false, "one" already in pool
pool[hash("one") --> "one"]
return pool[hash("one")]
Run Code Online (Sandbox Code Playgroud)
所以在这种情况下,变量a
和b
持有对同一对象的引用.在这种情况下,我们有(a == b) && (a.equals(b)) == true
.
如果我们使用构造函数,则不是这种情况:
1: a := "one"
2: b := new String("one")
Run Code Online (Sandbox Code Playgroud)
同样,"one"
在池上创建,但后来我们从同一个文字创建一个新实例,在这种情况下,它导致(a == b) && (a.equals(b)) == false
那我们为什么要有一个字符串池呢?字符串,尤其是字符串文字广泛用于典型的Java代码中.而且他们是不变的.并且不可变允许缓存String以节省内存并提高性能(创建的工作量更少,收集的垃圾更少).
作为程序员,我们不必太在意字符串池,只要我们记住:
(a == b) && (a.equals(b))
可能是true
或false
(总是使用equals
比较字符串)char[]
String 的后台(因为您不知道谁在使用该String实现) 归档时间: |
|
查看次数: |
111497 次 |
最近记录: |