String创建了几个对象

使用

1、String str = “hello”;
创建了一个对象
jvm在编译阶段会判断常量池中是否有“hello”这个常量对象,如果有,str就直接指向这个常量的引用,如果没有就会在常量池中创建这个对象。
2、String str = new String(“hello”);
创建了两个对象
jvm编译阶段会判断常量池中是否有“hello”这个常量对象,进而判断是否创建常量对象,然后运行阶段通过new关键字在java 堆上开辟一块儿空间来创建String 对象。
3、String str = “hello” + “world”;
创建了一个对象
jvm编译阶段通过编译器优化后,会把字符串常量直接合并成“helloworld”,所以在常量池中只创建了一个对象。
4、String str = new String(“he”) + new String(“llo”);
创建了六个对象
在字符串常量池通过字面量创建”he” 和 “llo”字符串对象,并保存其对象引用,以及在堆中创建”he” 和 “llo”字符串对象,另外底层是通过new StringBuilder().append(“he”).append(“llo”).toString()进行拼接。其中StringBuilder的toString()会生成一个新的字符串对象new String(“hello”),但由于这个代码是运行期动态生成的,所以不会在字符串常量池中创建字符串对象”hello”,但会在堆中创建字符串对象”hello”。

为什么要先在字符串常量池中创建对象

由于字符串的使用频率实在是太高了,所以 Java 虚拟机为了提高性能和减少内存开销,在创建字符串对象的时候进行了一些优化,特意为字符串开辟了一个字符串常量池。

intern方法

这个方法会随着JVM源码的变化而变化。还是要看源码的注释。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
* Returns a canonical representation for the string object.
* <p>
* A pool of strings, initially empty, is maintained privately by the
* class {@code String}.
* <p>
* When the intern method is invoked, if the pool already contains a
* string equal to this {@code String} object as determined by
* the {@link #equals(Object)} method, then the string from the pool is
* returned. Otherwise, this {@code String} object is added to the
* pool and a reference to this {@code String} object is returned.
* <p>
* It follows that for any two strings {@code s} and {@code t},
* {@code s.intern() == t.intern()} is {@code true}
* if and only if {@code s.equals(t)} is {@code true}.
* <p>
* All literal strings and string-valued constant expressions are
* interned. String literals are defined in section 3.10.5 of the
* <cite>The Java&trade; Language Specification</cite>.

返回字符串对象的规范表示。一个字符串池,最初是空的,由 String 类私下维护。当调用 intern 方法时,如果池中已经包含一个等于该 String 对象的字符串,由 equals(Object) 方法确定,则返回池中的字符串。否则,将此 String 对象添加到池中并返回对该 String 对象的引用。由此可见,对于任何两个字符串 s 和 t,当且仅当 s.equals(t) 为真时,s.intern() == t.intern() 才为真。所有文字字符串和字符串值的常量表达式都是实习的。字符串文字在 Java™ 语言规范的第 3.10.5 节中定义。
*
* @return a string that has the same contents as this string, but is
* guaranteed to be from a pool of unique strings.
与此字符串具有相同内容的字符串,但保证来自唯一字符串池。
*/
public native String intern();

根据注释,发现如果常量池中没有对象时,会创建一个常量池对象。

注释上同时说明对于任何两个字符串 s 和 t,当且仅当 s.equals(t) 为真时,s.intern() == t.intern() 才为真。

如果直接判断 s == t.intern() 这时不一定为真。如果使用intern方法尽量两边都使用。

Intern()方法一直返回的是字符串常量池中的对象,所以==判断时要先区分字符串不是来自常量池。


String创建了几个对象
http://hanqichuan.com/2019/07/18/java/String创建了几个对象/
作者
韩启川
发布于
2019年7月18日
许可协议