关于字符串常量池的那些事
字符串intern()特殊字符的问题
intern()方法是返回常量池中字符串的引用(针对java8而言),并且这个引用是该字符串第一次在堆中出现时的引用
直接上代码
String str = new StringBuilder("aaa").append("bbb").toString();
System.out.println(str.intern());//aaabbb
System.out.println(str == str.intern());//true
System.out.println();
String str2 = new StringBuilder("ja").append("va").toString();
System.out.println(str2.intern());//java
System.out.println(str2 == str2.intern());//false
是不是不相信自己的眼睛了,为什么上面的返回的是true,下面却是false呢?我也很懵,经过一系列懵逼以后,发现,不仅仅是java字符串会返回false,void、main、true、false都会返回false
这是为什么呢?需要弄清楚这个问题,我是这样开始分析的。
intern()返回值问题
System.out.println(str2 == str2.intern());//false
根据返回结果可知,肯定是常量池中存储的引用不是堆中“java”对象的地址
String str = "aaabbb";
String str1 = "aaabbb";
String str2 = new String("aaabbb");
System.out.println(str == str1);//true
System.out.println(str == str2);//false
System.out.println(str == str2.intern());//true
-
对于字面量赋值,在加载时,字符串就被创建于堆中了,同时在常量池中存放它的引用,也就是通过这种方式创建,只要值相同,不管你创建多少次,都会指定堆中同一个对象。
-
对于new方法赋值,则前面加载过程是一样的,不过无论常量池中有没有值相等的引用都会在堆中开辟空间创建对象。
有上面代码可以看出,常量池中存放的是第一次在堆中出现对象的引用。
那么我们的迷惑就稍微有点可以解开迷雾了,之所以java字符串和我们常量池中拿出的不相同,根本原因就是在我们的代码运行之前,java字符串已经加入常量池中了。
寻找在哪儿有定义该常量
直接上代码
public final class System {
private static void initializeSystemClass() {
...略
sun.misc.Version.init();
}
}
public class Version {
private static final String launcher_name = "java";
...略
}
好了,是不是清楚点了。。。
菜鸟求教,望高人指点
String str = "java";
System.out.println(str.intern());
System.out.println(str == str.intern());//true
??????
黑人问号脸,这。。。不就自动推翻了上文中:在自己代码加载之前java字符串已经加入常量池中的说法,我。。。望高人指点一下