下面两行Java代码创建了多少个对象?
String s = new String("Hello");
String s1 = s.toUpperCase();
我知道 toUpperCase() 会在堆中创建一个新对象。但是想知道会不会也放到String池里
答案是......这取决于。
我们可以肯定地说的一件事是,无论是
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常量的字符串。
号
您可以通过运行以下代码来测试它。
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 个对象。没有新的文字将被添加到字符串池中。
看看这个答案
错了请指正; “字符串常量池”只是堆的一部分,专门用于
String
值。这是
String
的+2String s = new String("Hello")
对象。String
.+1
String s1 = s.toUpperCase()
对象
此外,大多数 IDE 都允许您在调试过程中查看内存。