好像这个intern的方法,平时开发中并没有频繁使用。具体的使用场景,说实话我也不清楚。
对于intern的这个用法,不经常使用的话,总是容易忘记。总会被几个例子给弄晕。
于是,我打算写下自己的看法,以我自己的看法,这个intern方法,会将实例化对象的内容,存放到常量池中。
接下来,参照其他博主的解释,来说明一下intern
首先 http://www.runoob.com/java/java-string-intern.html
String a = "abc";
String b = "abc";
String c = "a" + "b" + "c";
String d = "a" + "bc";
String e = "ab" + "c";
System.out.println(a == b);
System.out.println(a == c);
System.out.println(a == d);
System.out.println(a == e);
System.out.println(c == d);
System.out.println(c == e);
运行结果:
true
true
true
true
true
true
上面的例子可以知道,它们都存在于字符串常量池中。==是用来比较地址是否相等的。那么,上面的结果都是true,说明他们的地址都是相同。原因是,在定义变量的时候赋值,如果赋值的是静态的字符串,就会执行进入字符串池的操作,如果池中含有该字符串,则返回引用。c/d/e虽然是多个字符串值相加,但是他们最终的结果都是abc,并且在字符串池中已经存在,那么就回直接返回相同的引用。 这个地方,感觉intern的方法也就是这样的。
用这位博主的解释来理解intern https://blog.csdn.net/believesoul/article/details/79588305
它的作用
那么看下面的例子:
String a = new String("abc");
// 第一次,创建了两个对象,一个是堆中的string对象,一个是常量池中的"abc"
String b = new String("abc");
// 第二次,创建一个对象,堆中的另外一个string对象
System.out.println(a.intern() == b.intern());// true
System.out.println(a.intern() == b);// false
System.out.println(a.intern() == a);// false
由于第一个对象a的创建,常量池已经有abc了,那么当a.intern() 在常量池就找到了这个abc,会直接返回"abc"字符串。
所以a.intern()与b.intern()返回的都是一样的常量字符串"abc"
而后面两个 a.intern()==b 和 a.intern()==a 都相当于是 "abc"==new String("abc") 当然就是false。(我是这么理解的)
String a = new String("abc");
// 第一次,创建了两个对象,一个是堆中的string对象,一个是常量池中的"abc"
String b = new String("abc");
// 第二次,创建一个对象,堆中的另外一个string对象
System.out.println(a.intern() == b.intern());// true
System.out.println(a.intern() == b);// false
System.out.println(a.intern() == a);// false
String poolstr = "abc";
// 直接从字符串常量池中获取
System.out.println(a.intern() == poolstr);// true
System.out.println(b.intern() == poolstr);// true
那么这个例子应该就好理解了。
a.intern()==poolstr 和 b.intern()==poolstr 都相当于是 "abc"=="abc" 相同的常量字符串 当然会是true
接下来的这个就有点难以理解
String str = new String("a") + new String("b");
System.out.println(str.intern() == str);// true
我认为这个str 创建了5个对象,new String("a")和new String("b") 各自创建了2个对象,2个在堆中,2个在常量池中a和b
还有第五个对象就是 堆中的"ab"。并没有在常量池中。
有这么一句话"对于所有包含new方式新建对象(包括null)和变量形式 的“+”连接表达式,它所产生的新对象都不会被加入字符串池中"(例如:new String("a") + new String("b")或是 new String("a")+变量c )
我觉得对上面这句话的解释:编译器认为new或变量不是字符串常量,所以不会进行优化放入常量池,而是直接创建一个新的对象引用。
刚好跟str的情况一下,这就是"ab"中没有在常量池中的原因。
接下来就是,为什么 str.intern()==str
在jdk1.7之后是查看常量池中是否存在和调用方法的字符串内容一样的字符串,
如果有的话,就返回该常量池中的字符串,
若没有的话,就在常量池中写入一个堆中该字符串对象的一个引用,指向堆中的该对象,并返回该引用。
就是后面这里,如果没有,就在常量池中写入一个堆中该字符串对象的引用,刚好str在堆中有"ab"的引用,所以它们两个是相等的。
另外一个例子
String 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);
System.out.println(b.intern() == c);
System.out.println(b.intern() == d);
System.out.println(b.intern() == f);
System.out.println(b.intern() == a.intern());
结果在 http://www.runoob.com/java/java-string-intern.html 找
提醒一下,这个f 就是字符串常量+变量 这个结果也不会 存入常量池中。