如果我们在 Java 中对字符串调用 subString() 或 toUpperCase() 等任何方法,会创建多少个对象?

问题描述 投票:0回答:3

下面两行Java代码创建了多少个对象?

String s = new String("Hello");
String s1 = s.toUpperCase();

我知道 toUpperCase() 会在堆中创建一个新对象。但是想知道会不会也放到String池里

java string jvm
3个回答
3
投票

答案是......这取决于。

我们可以肯定地说的一件事是,无论是

toUpperCase()
还是
subString()
都不会在字符串池
1
中放置一个String。唯一指定为(可能)将
String
添加到字符串池的
String
操作是
intern()
.

我们不能肯定地说

toUpperCase()
subString()
会生成一个新的
String
对象。例如,在 Java 11 中,
str.substring(0)
返回
str
本身。这是一个实现细节,但是许多操作的 javadoc 措辞如此,如果
this
满足要求,则返回
this
是有效的。

在创建新

String
的情况下,创建对象的方式取决于实现。 Java 字符串通常表示为一个
String
对象,它引用了表示字符串字符的后备
char[]
byte[]
。但是在某些 Java 版本中,支持数组可以在多个
String
对象之间共享......在某些情况下。事实上,
substring
是使用共享后备阵列创建
String
的方法之一。

最后,正如一位评论者所指出的,这些东西与现实世界中的 Java 编程无关……除了最极端的情况。通常,你应该让 JVM 处理这种东西。


1 - 它是字符串池而不是“常量字符串池”。 “常量池”实际上是类文件中存在的东西。但是字符串池中可能包含不对应Java常量的字符串。


1
投票

您可以通过运行以下代码来测试它。

    String s = new String("Hello");
    String upperS = "HELLO";
    String s1 = s.toUpperCase();
    System.out.println(s==s1);  //prints false
    System.out.println(upperS==s1);  //prints false

来自 Java 文档的§3.10.5

…一个字符串字面值总是指类 String 的同一个实例。这是因为字符串文字——或者更一般地说,作为常量表达式 (§15.29) 值的字符串——被“驻留”以便共享唯一实例,就像通过执行方法 String.intern (§12.5) 一样。

因此,字符串池仅包含来自 Java 源代码的字符串文字(如

"abc"
的表达式)和已调用其
.intern
方法的字符串。

在您的代码中,以下行在堆上创建一个字符串对象,但不是字符串池中的文字。

    String s = new String("Hello");

以下行还在堆中创建了另一个对象,但没有在字符串池中创建文字。

    String s1 = s.toUpperCase();

所以,在你的例子中。将在堆中创建 2 个对象。没有新的文字将被添加到字符串池中。

看看这个答案


0
投票

错了请指正; “字符串常量池”只是堆的一部分,专门用于

String
值。
因此,在堆中创建的是您所指的池。

这是

String
的+2
String s = new String("Hello")
对象。
并且,为
String
.
 +1 
String s1 = s.toUpperCase()

对象

此外,大多数 IDE 都允许您在调试过程中查看内存。

© www.soinside.com 2019 - 2024. All rights reserved.