当前位置: 首页 > 知识库问答 >
问题:

Java字符串池与字符串构造函数和实习生函数

欧博简
2023-03-14

我最近了解了Java字符串池,有几件事我不太明白。

使用赋值操作符时,如果字符串池中不存在新字符串,则将在字符串池中创建新字符串。

String a = "foo"; // Creates a new string in the String Pool
String b = "foo"; // Refers to the already existing string in the String Pool

当使用String构造函数时,我明白无论String池的状态如何,都将在堆中、String池之外创建一个新字符串。

String c = new String("foo"); // Creates a new string in the heap

我在某处读到过,即使在使用构造函数时,也在使用字符串池。它将把字符串插入到字符串池和堆中。

String d = new String("bar"); // Creates a new string in the String Pool and in the heap

我没有找到任何关于这方面的进一步信息,但我想知道这是不是真的。

如果这是真的,那么——为什么?为什么java会创建这个重复字符串?这对我来说似乎是完全多余的,因为java中的字符串是不可变的。

另一件事,我想知道的是如何。String类的intern()html" target="_blank">函数起作用:它是否只返回一个指向字符串池中字符串的指针?

最后,在以下代码中:

String s = new String("Hello");
s = s.intern();

垃圾收集器会从堆中删除字符串池之外的字符串吗?

共有2个答案

上官飞
2023-03-14

问:我在某个地方读到过,即使在使用构造函数时,也在使用字符串池。它将把字符串插入到字符串池和堆中。[:我没有找到任何关于这件事的进一步信息,但我想知道这是不是真的。

这不是真的。使用new创建的字符串未放置在字符串池中。。。除非有东西显式地调用它的intern()

问:为什么java会创建这个重复的字符串?

因为JLS指定每个new生成一个新对象。如果没有,那将是反直觉的(海事组织)。

在这种情况下,使用new String(String)几乎总是一个坏主意,这并不是让new表现不同的好理由。真正的答案是程序员应该学会不要写那些。。。除了极少数有必要这样做的情况。

问:我想知道的另一件事是String类的intern()函数是如何工作的:它是否只返回字符串池中的字符串指针?

intern方法始终返回指向字符串池中字符串的指针。该字符串可能是也可能不是您调用的intern()或。

字符串池的实现方式多种多样。

>

  • 在最初的方案中,驻留的字符串保存在一个称为PermGen堆的特殊堆中。在该方案中,如果您正在驻留的字符串尚未在池中,则将在PermGen空间中分配一个新字符串,并且intern方法将返回该字符串。

    在当前方案中,插入的字符串保存在普通堆中,字符串池只是一个(私有)数据结构。当被插入的字符串不在池中时,它只是链接到数据结构中。不需要分配新字符串。

    Q:垃圾收集器会从堆中删除字符串池之外的字符串吗?

    所有Java对象的规则都是相同的,不管它们是如何创建的,也不管它们位于何处(JVM中的“空间”或“堆”)。

    如果无法从正在运行的应用程序访问对象,则垃圾收集器可以删除该对象。

    这并不意味着无法访问的对象将在GC的任何特定运行中被垃圾收集。(在某些情况下,甚至永远不会。)

    上述规则同样适用于与字符串文字相对应的字符串对象。如果某个文本可能永远不能再使用,那么它可能会被垃圾收集。

    这通常不会发生。JVM在与定义它的类相关联的私有数据结构中保留对每个字符串文本对象的隐藏引用。由于类通常存在于JVM的生命周期中,所以它们的字符串文本对象仍然是可访问的。因为应用程序可能需要使用它们。)

    但是,如果使用动态创建的类加载器加载一个类,并且该类加载器变得不可访问,那么它的所有类都将无法访问。因此,字符串文字对象实际上可能变得不可访问。如果是这样,它可能会被垃圾收集。

  • 桑坚
    2023-03-14

    你写的

    String c = new String("foo"); // Creates a new string in the heap
    

    我在某处读到过,即使在使用构造函数时,也在使用字符串池。它将把字符串插入到字符串池和堆中。

    这有点正确,但您必须正确阅读代码。您的代码包含两个String实例。首先,您有一个字符串literal“foo”,它的计算结果是一个string实例,该实例将被插入池中。然后,使用newstring(…)调用String(String)构造函数,显式创建一个新的String实例。由于显式创建的对象不能与创建之前存在的对象具有相同的标识,因此必须存在两个String实例。

    为什么java会创建这个重复字符串?这对我来说似乎是完全多余的,因为java中的字符串是不可变的。

    它确实如此,因为你是这么说的。理论上,这种结构可以得到优化,跳过你无论如何都无法感知的中间步骤。但是程序行为的第一个假设应该是它完全按照你写的做。

    你可以问为什么有一个构造函数允许这样一个无意义的操作。事实上,以前有人问过这个问题,这个答案解决了这个问题。简言之,这主要是一个历史性的设计错误,但由于其他技术原因,该构造器已在实践中使用;有些不再适用。但是,如果不破坏兼容性,就无法删除它。

    String s = new String("Hello");
    s = s.intern();
    

    垃圾收集器会从堆中删除字符串池之外的字符串吗?

    由于intern()调用将计算为“Hello”创建的实例,并且与通过新字符串(…)创建的实例不同,后者在第二次分配给s后肯定无法访问。当然,这并不是说垃圾收集器是否会回收字符串的内存,只是允许它这样做。但是请记住,堆占用的大部分将是保存字符数据的数组,这些字符数据将在两个字符串实例之间共享(除非使用非常过时的JVM)。只要两个字符串中的任何一个正在使用,此数组仍将被使用。最近的JVM甚至具有字符串重复数据消除功能,这可能会导致JVM中具有相同内容的其他字符串使用此数组(以允许收集以前使用的数组)。因此,阵列的生存期是完全不可预测的。

     类似资料:
    • 问题内容: 我正在查看String API,突然我遇到了一个String空的构造方法,即我们可以使用以下方法构造一个空的String对象: 我不知道有什么用吗? 问题答案: 当然..... 将在堆创建一个非文字串对象 ,这 将是 垃圾收集。 在哪里 将创建一个String Literal 。这 将不会被 垃圾收集过,如果是通过默认加载器访问。 看到下面这个链接,我问了一个问题。这可能与您的问题没有

    • 问题内容: 以下两段代码是否相同? 问题答案: 它们具有相同的 最终结果 ,但它们并不相同(它们将产生不同的字节码;版本实际上经过了这些步骤,生成了新的字符串对象,然后对其进行中间化)。 来自以下两个相关引号: 调用该方法时,如果池中已经包含与该方法确定的对象相等的字符串,则返回池中的字符串。否则,将此对象添加到池中,并返回对该对象的引用。 所有文字字符串和字符串值常量表达式都将被插入。 因此,

    • 这些函数在字符数组类(numpy.char)中定义。 较旧的 Numarray 包包含chararray类。 numpy.char类中的上述函数在执行向量化字符串操作时非常有用。 函数执行按元素的字符串连接。 输出如下: 连接两个字符串: ['hello xyz'] 连接示例: ['hello abc' 'hi xyz'] numpy.char.multiply() 这个函数执行多重连接。 imp

    • 字符串函数简介 字符串函数主要用于字符串的转码、替换、格式化等方面,可以帮助我们快速简便的处理字符串。 3.1 escape 函数 函数用途: 将URL编码应用于在输入字符串中找到的特殊字符。 tips: 以下这些字符不会参与编码:, , / , ? , @ , & , + , ' , ~ , ! , $ 常见的编码字符: <space> , # , ^ , ( , ) , { , } , | ,

    • Vim有许多内置(built-in)函数来操作字符串。本章中我们将介绍一些最为重要的字符串函数。 长度 第一个介绍的函数是strlen。执行下面的命令: :::vim :echom strlen("foo") Vim显示3,也即"foo"的长度。现在尝试下面的命令: :::vim :echom len("foo") Vim再一次显示3。对于字符串,len和strlen有同样的效果。在本书稍后的

    • 我正在做一项关于使用结构化/半结构化/非结构化数据的作业,我正在对莎士比亚的戏剧进行字数统计(以了解语言如何随时间变化),方法是导入每部戏剧的txt文件和xml索引文件,该文件存储有关每部戏剧的关键信息,如编写年份、角色列表等。。然后,我将删除字符名、设置、标点符号和常用词(和、但、或,如果等…)从txt文件准备好进行字数统计-全部在C#中运行的控制台脚本中。我正在编写一个类,每个剧本的数据都将存