关于字符串在常量池中中的存储问题
package com.xwl;
/**
* 关于常量池的问题
* @author Administrator
* 字符串常量池
*/
public class AboutInterview {
public static void main(String[] args) {
String s1 = "hello";
String s2 = "hello";
String s3 = "he" + "llo";
String s4 = "hel" + new String("lo");
String s5 = new String("hello");
String s6 = s5.intern();
String s7 = "h";
String s8 = "ello";
String s9 = s7 + s8;
System.out.println(s1==s2);//true s1创建后在串池中,s2创建时候发现已经有,这返回s1的地址 因此相等
System.out.println(s1==s3);//true s3字符串拼接后就是s1 jvm在编译期间就已经对它进行优化 因此相等
System.out.println(s1==s4);//false
/**
* s4中的new String("lo")生成了两个对象,"lo","new String("lo")",
*"lo"存在字符串常量池,"new String("lo")"存在堆中,
*String s4 = "hel" + new String("lo")实质上是两个对象的相加,
*编译器不会进行优化,相加的结果存在堆中,而s1存在字符串常量池中,当然不相等。
*/
System.out.println(s1==s9);//false
System.out.println(s4==s5);//false
System.out.println(s1==s6);//true
System.out.println("-----------------------------------");
String c1 = new String("hello");
String c2 = "hello";
String intern1 = c1.intern();
System.out.println(intern1 == c2);
String c3 = new String("hello") + new String("hello");
String c4 = "hellohello";
String intern3 = c3.intern();
System.out.println(intern3 == c4);
/**
* jdk1.6下字符串常量池是在永久区中,是与堆完全独立的两个空间,
* c1指向堆中的内容,c2指向字符串常量池中的内容,两者当然不一样,
* c1.intern1()将字面量加入字符串常量池中,
* 由于字符串常量池中已经存在该字面量,所以返回该字面量的唯一引用,intern1==c2就输出true。
* jdk1.7,1.8下字符串常量池已经转移到堆中了,是堆中的一部分内容,
* jvm设计人员对intern()进行了一些修改.
* 当执行c3.intern()时,jvm不再把s3对应的字面量复制一份到字符串常量池中,
* 而是在字符串常量池中存储一份s3的引用,这个引用指向堆中的字面量,
* 当运行到String c4 = "hellohello"时,
* 发现字符串常量池已经存在一个指向堆中该字面量的引用,则返回这个引用,而这个引用就是c3。所以c3==c4输出true。
*/
System.out.println("---------------------");
String d1 = new String("hello");
String d2 = "hello";
String inter1 = d1.intern();
System.out.println(d1 == d2);
String d3 = new String("hello") + new String("hello");
String d4 = "hellohello";
String inter3 = d3.intern();
System.out.println(d3 == d4);
/**
* s3指向堆内容,接着s4="hellohello"发现字符串常量池中没有该字面量,创建并返回该引用。
* s3,s4一个在堆,一个在字符串常量池,是两个独立的引用,所以s3==s4输出false。
*/
}
}