intern()是String一个api,平时不常用,但是面试可能会考,掌握intern可避免被面试官问到时大眼瞪小眼的尴尬局面。
当一个String对象调用intern()方法时,会首先检查字符串常量池中是否存在equals相等的字符串,若存在直接返回常量池中该字符串对象,否则创建该字符串对象并放入字符串常量池。
然而并不是所有创建的字符串都会进入常量池。下面直接贴代码,每行代码都通过备注的形式给出了运行结果和相关解释。
String a = new String("ab"); //开辟新的堆内存,存放字符串对象"ab",引用为 a,同时"ab"进入字符串常量池
String b = new String("ab"); //开辟新的堆内存,存放字符串对象"ab",引用为 b,同时"ab"指向字符串常量池已有的对象
String c = "ab"; //未开辟新的堆内存,直接将引用c指向了字符串常量池已有的"ab"
String d = "a" + "b"; //通过拼接静态字符串的方式先检查常量池中是否已有相等的对象,有则直接将引用指向和c相同的对象
String e = "b"; //引用e指向一个新的字符串
String f = "a" + e; //和e拼接将产生一个新的对象,即f指向新的内存地址
System.out.println(c == d); //true //d通过+拼接的是静态字符串,非引用
System.out.println(f == d); //false //f通过+拼接了一个引用相当于新创建了一个对象。
//通过new 创建的字符串对象(a本身,b本身)不会进入字符串常量池
System.out.println(a == a.intern()); //false,a没有进入常量池,但是a.intern()已经进入,二者非同一对象
System.out.println(c == c.intern()); //true,c本来就在字符串常量池,所以返回true
System.out.println(b.intern() == a); //false,a没有进入常量池,但是b.intern()已经进入且和a.intern()是同一个对象
System.out.println(b.intern() == c); //true, b.intern()进入了常量池,c和该池子中的对象
//通过+拼接静态字符串得到的字符串对象会进入字符串常量池
System.out.println(b.intern() == d); //true
//非静态字符串通过+拼接不会进入字符串常量池
System.out.println(b.intern() == f); //false
System.out.println(b.intern() == a.intern()); //true
大体总结3点:
1.new String的方式创建字符串对象,构造器参数进入字符串常量池,但是对象本身和常量池中的对象是两个不同的对象。从而导致这种方式产生的字符串调用intern()方法和本身引用 == 将返回false。
2.静态声明的方式定义的字符串直接进入字符串常量池,如常量池已有该字符串,则直接指向已有字符串。这种方式产生的字符串调用intern()方法和本身引用==始终返回true。
3.+拼接静态字符串创建的对象会进入字符串常量池,但是+拼接字符串引用就不会进入常量池。二者会导致完全不同的结果,前者调用intern()和自身==返回true,后者调用intern()和自身==返回false。