String对象创建的几种方式及创建过程中和String常量池的交互
1."" :最简单的创建方式;先判断常量池中是否有此字符串:没有 在常量池创建,返回常量池中的地址;有:直接返回常量池中的地址
2. new String(""):等价于""+new String(param);先判断常量池中是否有此字符串:没有 先在常量池创建,再在堆上创建,返回堆地址;有:只在堆上创建,返回堆地址
3. new String(param):先判断常量池中是否有此字符串:没有 在堆上创建,返回堆地址(jdk1.7+可能会被加入到常量池);有:只在堆上创建,返回堆地址
4. +:连接两个编译期可确定(""+"“或者两个final类型的变量)的两个变量等价于”";其他+相当于调用StringBuilder的append()方法,本质new String(param)
intern()方法
官方注释 :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.
当调用intern方法时,如果池中已经包含了一个与这个对象相等的字符串,则返回池中的字符串。否则,将这个对象添加到池中,并返回对这个对象的引用.不存在时jdk1.6将该对象的copy加入到常量池,返回常量池中的地址(多创建一个对象在常量池);jdk1.7将该对象加入到常量池,返回常量池中的地址(同一个对象).
下面看一些String的面试题
String s1 = "Hel" + new String("lo");
String s2 = s1.intern();
String s3 = "Hello";
String s4 = "Hel" + "lo";
String s5 = new String("Hello");
String s6 = s5.intern();
String s7 = "H";
String s8 = "ello";
String s9 = s7 + s8;
final String s10 = "H";
final String s11 = "ello";
String s12 = s10 + s11;
//jdk1.7+结果
System.out.println(s3 == s1);// true
System.out.println(s3 == s2);// true
System.out.println(s3 == s4);// true
System.out.println(s3 == s5);// false
System.out.println(s3 == s6);// true
System.out.println(s3 == s9);// false
System.out.println(s3 == s12);// true
//jdk1.6结果
System.out.println(s3 == s1);// false
System.out.println(s3 == s2);// true
System.out.println(s3 == s4);// true
System.out.println(s3 == s5);// false
System.out.println(s3 == s6);// true
System.out.println(s3 == s9);// false
System.out.println(s3 == s12);// true
jdk1.7+测试常量池中是否有某一个常量
//判断常量池是否有hello
String s1 = "he";
String s2 = "llo";
String s3 = new String(s1) + new String(s2);
String s4 = s3.intern();
System.out.println(s3==s4);//true:不存在,false:存在
//判断常量池是否有b(字符串"b",不是字符'b')
char[] cs1 = { 'b' };
String s1 = new String(cs1);
String s2 = s1.intern()
System.out.println(s1 == s2);//true:不存在,false:存在
另外jdk1.8常量池中内置一些字符串(a,10,11,12,java等等)
String s1 = new String("ja") + new String("va");
String s2 = new String("he") + new String("llo");
//jdk1.7
System.out.println(s1 == s1.intern());// true
System.out.println(s2 == s2.intern());// true
//jdk1.8
System.out.println(s1 == s1.intern());// false
System.out.println(s2 == s2.intern());// true