字符串常量是编译时确定的,编译完成,生成class文件,那就不会再变了。在编译的时候,编译器会将字符串常量直接放在一起,然后查找常量池里面,有没有对应的字符串。12345678910String str1= new String("abc");String str2= "abc";String str3= "a"+ "b"+ "c";System.out.println(str1== str2); //输出falseSystem.out.println(str1.intern()== str2); //输出true//intern()方法返回字符串对象的规范化表示形式。System.out.println(str2== str3); //输出trueString str4= "ab";String str5= str4+ "c";System.out.println(str2== str5); //输出false
- 第一个
str1== str2
对比的是引用的地址是否相同,由于str1采用的是new String
方式定义的,所以地址引用一定不相等。 - 第二个
str1.intern()== str2
,当str1调用intern的时候,会检查字符串池中是否含有 该字符串。由于定义的str2已经进入字符串池中,所以会得到相同的引用。 - 定义str3,在编译的时候,编译器会将字符串常量直接放在一起,然后查找常量池里面,有没有对应的字符串,所以str2和str3是相等的,也就是指向相同的内存区域。
- 看一下下面的代码123456789101112String a = new String("ab");String b = new String("ab");String c = "ab";String d = "a" + "b";String e = "b";String f = "a" + e;System.out.println(b.intern() == a); //输出falseSystem.out.println(b.intern() == c); //输出trueSystem.out.println(b.intern() == d); //输出trueSystem.out.println(b.intern() == f); //输出falseSystem.out.println(b.intern() == a.intern()); //输出true
由运行结果可以看出来,b.intern() == a和b.intern() == c可知,采用new 创建的字符串对象不进入字符串池,并且通过b.intern() == d和b.intern() == f可知,字符串相加的时候,都是静态字符串的结果会添加到字符串池,如果其中含有变量(如f中的e)则不会进入字符串池中。但是字符串一旦进入字符串池中,就会先查找池中有无此对象。如果有此对象,则让对象引用指向此对象。如果无此对象,则先创建此对象,再让对象引用指向此对象。