当前位置: 首页 > 面试题库 >

Java字符串不变性和使用相同的字符串值创建新的字符串

柯冯浩
2023-03-14
问题内容

我知道问题的标题不是很清楚,对此感到抱歉,不知道如何提出。我有一个非常基本的Java实现问题,我想着重于应用程序性能,但是它也涉及Java中的String创建模式

我了解Java中字符串的不变性概念。我不确定的是,我在某处读到以下内容不会创建两个不同的String对象:

String name = "Sambhav";
String myName= "Sambhav";

我想知道Java是怎么做到的?它实际上是否在程序存储器中寻找一个String值并检查其是否存在,如果不存在则创建一个新的String对象?在那种情况下,显然可以节省内存,但存在性能问题。

还可以说我有这样的代码:

  public void some_method(){
        String name = "Sambhav";
        System.out.println(name); //  or any random stufff
  }

现在,在每次调用此函数时,是否正在创建一个新的String并将其添加到内存中,或者我是否使用相同的String对象?我只是想知道所有事情的真相?

如果我们这样说

String name = "Sambhav";
String myName= "Sambhav";

不会因为引用而创建新对象,那

String name = new String("Sambhav");
String myName= new String("Sambhav");

Java是否仍然可以捕捉到该字符串相同,只是将myName指向与上一条语句中创建的对象相同的对象?


问题答案:

字符串是内部char数组,具有一些与基础char数组一起使用的固有功能。例如。subString(int),split(String)方法。

字符串是不可变的,这意味着更改字符串引用所做的任何努力都会创建一个新的字符串并为此分配内存。如下

line 1. String a = new String("SomeString");
line 2. a = "SomeStringChanged";

第1行使用变量a引用的“ SomeString”分配内存,并将“ SomeString ” 添加到 字符串池

第2行在 字符串池中 使用“ SomeStringChanged” 分配内存,并被aie a引用,现在不指向“ SomeString”,并且“
SomeString”占用的内存现在可用于 gc

这里没有重复使用

line 3. String  b =  "SomeStringChanged";

现在,文字“ SomeStringChanged* ”被变量 ab 重用 。也就是说,它们指的是 相同的内存位置
,实际上是指称为“ 字符串池 ”的位置。
***

line 4. a = new String("SomeStringChanged");

现在,新的分配完成包含“ SomeStringChanged ”,并引用 一个

没有再使用 ,现在发生的事情。(字符数组 SomeStringChanged的 字符串池中已经存在。因此,没有字符串池分配发生)

line 5. a = new String("SomeStringChanged").intern();

现在,在第4行中创建的分配将被丢弃,变量 ab 指向包含“
SomeStringChanged”的字符串池中的相同位置。这里重复使用相同的char数组。功劳归于 intern() 方法

line 6. String x = new String("SomeX");
line 7. String y = "SomeX";

第6 行将 在堆和字符串池中为 SomeX 创建一个分配。char数组已重复。

第7行不会为 SomeX 分配任何内存,因为它已经在字符串池中了

Line 8 String s = new String(someStringVariable);

第8行将仅在堆中分配单个内存位置,而不在字符串池中分配单个内存位置。

总之,只有在将String引用声明为文字或将String对象插入的情况下,才可以重用字符串的char数组,即只有这两个可以使用String池(这实际上是char数组重用的思想)。



 类似资料:
  • 当使用关键字 new 创建字符串时,它使用采用 String 文本的构造函数创建新的 String 对象。我想知道在调用 String 构造函数之前,文本是否存储在常量池中。 我这么问的原因是,在《OCA Java SE 7程序员I认证指南》中,Mala Gupta写道: 她在第一行表示,new创建的String对象不会存储在常量池中。这很好,但不清楚的是,第一行构造函数中的字面“Summer”是

  • 问题内容: 有人告诉我不能更改Java中的字符串。下面的代码呢? 它不改变字符串吗?另外,replace()的实现在哪里;相比于(); 等于(); 提供?我只是在这里使用这些功能,但实际上在哪里实现? 问题答案: String.replace()返回一个新的String。 “名称”是对String对象的引用,因此可以将其重新分配为指向name.replace(),但它将指向一个新对象。 这是Str

  • 问题内容: 考虑以下示例。 现在,在Java中,String对象是不可变的。然后如何为对象分配值“帮助!”。这是否与Java中字符串的不变性相矛盾?有人可以向我解释不变性的确切概念吗? 编辑: 好。我现在明白了,但只是一个后续问题。那么下面的代码呢: 这是否意味着将再次创建两个对象(“密西西比”和“ M!ss!ss!pp!”),并且引用在方法之后指向另一个对象? 问题答案: 不是对象,而是对对象的

  • 我试图创建一个表示JSON对象数组的字符串文字,所以我想到了使用字符串插值特性,如下面的代码所示: 现在我想使用逐字字符串,这样我就不必使用反斜杠来转义双引号。因此,通过这个答案,我了解到逐字字符串和字符串插值可以一起使用。所以我改变了我的代码如下: 但它无法编译。如果我的用法有任何错误,或者在这种情况下无法使用C#的逐字字符串功能转义双引号,有人能帮我吗?

  • 我想从字符串创建UUID,以便为特定字符串输入生成相同的UUID。这说明了如何在Java中实现它,但有没有办法在QT5中实现它?

  • 问题内容: 想知道有没有比如下计算给定字符串的字符数更简单的方法? 问题答案: 具有完全的Unicode支持(Java 11+)1的最简单的方法来计算字符串中每个字符的出现次数: 1)答案的结尾是具有完整Unicode支持的Java 8版本。 输出量 更新: 对于Java 8+(不支持补充平面中的字符,例如emoji): 更新2: 同样适用于Java 8+。 我误会了,以为它是在Java 9之前才