Java中的字符串池是什么?[重复]

2020/12/31 23:31 · java ·  · 0评论

我对Java中的StringPool感到困惑。我在阅读Java中的String一章时遇到了这个问题。用外行的术语,请帮助我了解StringPool的实际作用。

打印true(即使我们不使用equals方法:比较字符串的正确方法)

    String s = "a" + "bc";
    String t = "ab" + "c";
    System.out.println(s == t);

当编译器优化您的字符串文字时,它会看到两者st具有相同的值,因此您只需要一个字符串对象。这是安全的,因为String在Java中是不可变的。

结果,两者
s和都t指向同一个对象,节省了一些内存。

名称“字符串池”的想法是,所有已经定义的字符串都存储在某个“池”中,并且在创建新的String对象编译器之前检查是否已经定义了这样的字符串。

我认为它实际上并没有太大作用,它看起来只是字符串文字的缓存。如果您有多个值相同的字符串,它们都将指向字符串池中的相同字符串文字。

String s1 = "Arul"; //case 1 
String s2 = "Arul"; //case 2 

在情况1中,立即创建文字s1并将其保存在池中。但是在情况2中,文字s2引用了s1,它不会创建新的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.  

http://p2p.wrox.com/java-espanol/29312-string-pooling.html

让我们从虚拟机规格的引言开始:

加载包含String文字的类或接口可能会创建一个新的String对象(第2.4.8节)来表示该文字。如果已经创建了一个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")] 

因此,在这种情况下,变量ab保持对同一对象的引用在这种情况下,我们有(a == b) && (a.equals(b)) == true

如果使用构造函数,则不是这种情况:

1: a := "one"
2: b := new String("one")

再次,"one"在池上创建,但随后我们使用相同的文字创建一个新实例,在这种情况下,它导致(a == b) && (a.equals(b)) == false

为什么要有一个字符串池呢?字符串,尤其是字符串文字,在典型的Java代码中被广泛使用。他们是一成不变的。并且由于是不可变的,因此可以缓存String以节省内存并提高性能(减少创建工作量,减少收集的垃圾)。

作为程序员,只要记住以下几点,我们就不必关心字符串池:

  • (a == b) && (a.equals(b))可能是truefalse始终用于equals比较字符串)
  • 不要使用反射来更改char[]字符串的支持(因为您不知道谁正在使用该字符串)

当JVM加载类时,或者以其他方式看到文字字符串或某些代码intern字符串时,它会将字符串添加到一个大多为隐藏的查找表中,该表具有每个此类字符串的一个副本。如果添加了另一个副本,则运行时会对其进行排列,以使所有文字都引用相同的字符串对象。这称为“实习”。如果你说类似

String s = "test";
return (s == "test");

它会返回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"
本文地址:http://java.askforanswer.com/javazhongdezifuchuanchishishenmezhongfu.html
文章标签:
版权声明:本文为原创文章,版权归 admin 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!