20220629_String 类的 intern 方法
20220629_String类的intern方法
好久不见!
好久不见!!!
最近事情挺多,还好负责的迭代快上线了可以摸一下。在公司,外包仔可不敢用公司电脑登录摸鱼派。
正文
环境是JDK1.8,然后有这么一段代码:
/**
* @author LLaamar
* @date 2022/6/29 20:17
*/
public class InternTest {
public static void main(String[] args) {
String str = new StringBuilder().append("摸鱼").toString();
System.out.println(str == str.intern());
System.out.println("————————————————分割线————————————————");
String str2 = new StringBuilder().append("摸鱼").append("π").toString();
System.out.println(str2 == str2.intern());
}
}
执行结果如下:
false
————————————————分割线————————————————
true
很好奇,为什么?
不就是多了次append() ?为啥一个false一个true?
看到这里的可以停下来思考下为什么,没看到的可以看到以后再思考。
我翻了**append()的源码没找到答案,翻了toString()**的源码也没找到答案,发到公司后端群里引起激烈讨论,大家纷纷开始摸鱼讨论,最终在一位不知名大佬的帮助下找到答案——intern方法。
点进intern方法的源码可以看到,除了一串英文注释啥也没有。。。
大佬解释道:还是看下注释吧。。。
注释一长串,翻译也是有点烂,想必大家也懒得看(还有点押韵,skr~)
大致意思是,intern方法执行时会去查看常量池中是否已经有该字符串常量的引用,如果有,则返回。如果没有,就在常量池中创建引用,指向堆,再返回字符串在常量池中的引用。
所以,上面的代码可以有如下的注释:
/**
* @author LLaamar
* @date 2022/6/29 20:17
*/
public class InternTest {
public static void main(String[] args) {
// str是通过new声明的对象,存在于堆中
// 常量"摸鱼"被显示声明,此时"摸鱼"将存在于常量池中,并且常量"摸鱼"与str没有关系
String str = new StringBuilder().append("摸鱼").toString();
// str.intern()将返回常量池中的常量"摸鱼",此时==结果为false
System.out.println(str == str.intern());
System.out.println("————————————————分割线————————————————");
// str是通过new声明的对象,存在于堆中,str的内容是"摸鱼π"
// 常量"摸鱼"、"π"被显示声明,存在于常量池中
String str2 = new StringBuilder().append("摸鱼").append("π").toString();
// 常量池中不存在常量"摸鱼π",则str2.intern()将会在常量池中创建引用,该引用指向堆中的str2,返回str2的地址,此时==结果为true
System.out.println(str2 == str2.intern());
}
}
说起来是有点绕的,最后留个思考题:
public class InternTest {
public static void main(String[] args) {
String tk = "摸鱼π";
String str3 = new StringBuilder().append("摸鱼").append("π").toString();
System.out.println(str3 == str3.intern());
}
}
不懂的可以多看看上面的解释,懂的可以在评论区装个B。
那就这样,我们下期,再见。
努力让自己不那么菜
欲速则不达,每天进步一点点。
为false 因为tk在常量池中,str3是new出来的,所以在堆里面也有,==比较的是地址值。所以为false 不知道对不对
下期呢?