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 |
|
根据注释,发现如果常量池中没有对象时,会创建一个常量池对象。
注释上同时说明对于任何两个字符串 s 和 t,当且仅当 s.equals(t) 为真时,s.intern() == t.intern() 才为真。
如果直接判断 s == t.intern() 这时不一定为真。如果使用intern方法尽量两边都使用。
Intern()方法一直返回的是字符串常量池中的对象,所以==判断时要先区分字符串不是来自常量池。