JAVA字符串常量池你弄懂了吗?看看这个10个问题你能不能回答正确
/**
* @author humorchen
* @date 2021/12/28 10:43
*/
public static void main(String[] args) throws InterruptedException {
String s = new String("1");
String intern = s.intern();
String s1 = "1";
String s2 = new String("1");
System.out.println("s == intern \t" + (s == intern));
System.out.println("s == s1 \t" + (s == s1));
System.out.println("intern == s1 \t" + (intern == s1));
System.out.println("s == s2 \t" + (s == s2));
System.out.println("s.intern() == s2.intern() \t" + (s.intern() == s2.intern()));
String s3 = new String("1") + new String("1");
String s4 = "11";
System.out.println("s3 == s4 \t" + (s3 == s4));
System.out.println("s3.intern() == s4 \t" + (s3.intern() == s4));
String s5 = new String("2") + new String("2");
s5.intern();
String s6 = "22";
System.out.println("s5 == s6 \t" + (s5 == s6));
System.out.println("s5.intern() == s6 \t" + (s5.intern() == s6));
String s7 = s5.intern();
System.out.println("s5 == s7 \t" + (s5 == s7));
}
请开始你的代码阅读和思考答案下面将贴出答案,先思考好再看答案。
对完答案之后,很多人应该就懵懵的了吧。下面我来解答一下
public static void main(String[] args) throws InterruptedException {
String s = new String("1");
/**
* 第一步,"1",在常量池里创建一个"1"字符串对象,假设内存地址为 pool-1
* 第二步,new String在堆中创建一个String对象,字符数组为['1'],假设内存地址为 heep-s
* 第三步,创建变量s,类型String,引用第二步在堆中创建的对象的地址,也就是引用的 heep-s
*/
String intern = s.intern();
/**
* 第一步,s.intern(),在常量池查找有没有s这个字符串,如果有直接返回常量池里这个字符串,如果没有则将该字符串加入常量池,并返回该字符串,发现有,地址为 pool-1
* 第二步,创建变量intern,类型String,引用常量池中这个字符串的地址,也就是引用的 pool-1
*/
String s1 = "1";
/**
* 第一步,"1",发现常量池中已经有"1"了,返回常量池中“1”这个字符串对象,地址为 pool-1
* 第二步,创建变量s1,类型String,引用常量池当中这个字符串的地址,也就是 pool-1
*/
String s2 = new String("1");
/**
* 第一步,"1",查常量池里有没有,发现有"1",地址为 pool-1
* 第二步,new String,在堆当中创建一个String对象,字符数组为['1'],假设内存地址为 heap-s2
*/
System.out.println("s == intern \t" + (s == intern));
/**
* s = heep-s
* intern = pool-1
* 因此返回false
*/
System.out.println("s == s1 \t" + (s == s1));
/**
* s = heep-s
* s1 = pool-1
* 因此返回false
*/
System.out.println("intern == s1 \t" + (intern == s1));
/**
* intern = pool-1
* s1 = pool-1
* 因此返回true
*/
System.out.println("s == s2 \t" + (s == s2));
/**
* s = heep-s
* s2 = heep-s2
* 因此返回false
*/
System.out.println("s.intern() == s2.intern() \t" + (s.intern() == s2.intern()));
/**
* s.intern = pool-1
* s2.intern = pool-1
* 因此返回true
*/
String s3 = new String("1") + new String("1");
/**
* 第一步,"1",发现常量池里已经有了,地址为 pool-1
* 第二步,new String,创建了两个匿名的String对象,每个自己的字符数组都是['1'],这两个匿名对象后续在垃圾回收的时候会被回收的
* 第三步,创建一个StringBuilder,append("1"),append("1"),字符数组为['1','1'],也就是“11”,append完毕走stringBuilder.toString返回在堆里创建的String对象,假设内存地址为 heap-s3
* 第四步,创建变量s3,类型String,引用地址为 heap-s3
*/
String s4 = "11";
/**
* 第一步,"11",发现常量池里没有,加入常量池,假设地址为 pool-11
* 第二步,创建一个变量s4,类型String,引用地址 pool-11
*/
System.out.println("s3 == s4 \t" + (s3 == s4));
/**
* s3 = heap-s3
* s4 = pool-11
* 因此返回false
*/
System.out.println("s3.intern() == s4 \t" + (s3.intern() == s4));
/**
* s3.intern = "11"在常量池里的地址,也就是等于 pool-11
* s4 = pool-11
* 因此返回true
*/
String s5 = new String("2") + new String("2");
/**
* 第一步,"2",入常量池,假设地址为 pool-2
* 第二步,new String,创建两个匿名对象在堆里,后续垃圾回收会回收掉的
* 第三步,组装起来,创建一个StringBuilder,将两个String append进去,最后调用这个StringBuilder的toString返回组装好的String对象(堆里),内部的字符数组为['2','2'],假设内存地址为 heap-s5
* 第四步,创建变量s5,类型String,引用地址为 heap-s5
*/
s5.intern();
/**
* 第一步,s5.intern(),将s5的字符串"22"放入字符串常量池,这个时候常量池里没有"22",因此在常量池中创建了一个字符串"22"的对象,引用地址为s5,并返回s5的地址 heap-s5
*/
String s6 = "22";
/**
* 第一步,"22",检查常量池发现已经有了"22",因此返回内存地址 heap-s5
* 第二步,创建变量s6,类型String,引用地址为 heap-s5
*/
System.out.println("s5 == s6 \t" + (s5 == s6));
/**
* s5 = heap-s5
* s6 = heap-s5
* 因此返回true
*/
System.out.println("s5.intern() == s6 \t" + (s5.intern() == s6));
/**
* s5.intern =s5这个字符串在常量池里的地址 = heap-s5
* s6 = heap-s5
*/
String s7 = s5.intern();
/**
* 第一步,s5.intern(),检查s5的字符串是不是在常量池,发现已经在了,返回常量池里这个字符串“22”的引用地址 heap-s5
* 第二步,定义变量s7,类型String,引用地址为 heap-s5
*/
System.out.println("s5 == s7 \t" + (s5 == s7));
/**
* s5 = heap-s5
* s7 = heap-s5
* 因此返回true
*/
}